欢迎光临散文网 会员登陆 & 注册

javaUDP协议DatagramPacket、DatagramSocket

2022-09-13 09:00 作者:虚云幻仙  | 我要投稿

/**
* UDP协议,TCP/IP协议族中的协议,面向无连接,通信不需要建立连接(三次握手四次挥手),可能发生丢包乱序错包重复包,效率高于TCP,常用于游戏和视频通话
*/

public class DatagramPacket1 {
   public static void main(String[] args) {
       //UDP同样需要先创建服务端/接收方
       DatagramSocket ds = null;
       try {
           DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
           //datagram数据报packet包,UDP使用数据报包封装数据,发送方发送数据报包,接收方接收数据报包
           //服务端/接收方的数据报包对象的构造器需要:用于存放接收到的数据的字节数组byte[]、字节数组的可用长度(还可以指定存放的起始位置offset,不写默认从0位开始)

           ds = new DatagramSocket(9999);
           //通过DatagramSocket类发送/接收数据报包,需要指定端口用于发送/接收
           ds.receive(dp);
           //.receive(DatagramPacket)阻塞,等待接收数据,将收到的数据放入准备好的接收用数据报包中
           System.out.println(new String(dp.getData(),dp.getOffset(),dp.getLength()));
           //.getData()返回数据报包中的字节数据,new String(byte[])将数据转为字符串,因为数组可能没有放满,所以需要指定长度
           //.getOffset()返回数据开始位置 .getLength()返回数据实际长度

       } catch (IOException e) {
           throw new RuntimeException(e);
       } finally {
           if (ds != null) {
               ds.close();
               //DatagramSocket使用端口,用完需要关闭通道
           }
       }
   }
}

class UDPClient{
   public static void main(String[] args) {
       //通过客户端/发送方发送数据
       byte[] data = "将需要发送的数据转换为字节数组".getBytes();
       DatagramPacket dp = null;
       try {
           dp = new DatagramPacket(data,0,data.length,InetAddress.getLocalHost(),9999);
           //客户端/发送方构造器需要:存放了要发送的数据的字节数组、数据起始位置offset(不写默认从0位开始)、数据实际长度、用于指定发送地址IP:port的SocketAddress抽象类(子类为InetSocketAddress)(也可以用InetAddress指定ip,再加int port指定端口)
           //接收方不需要指定地址,发送方需要指定地址

           try(DatagramSocket ds = new DatagramSocket(8888)) {
               //与TCP不同的是,UDP发送方和接收方使用同一个类DatagramSocket,因为不需要建立连接,所以从一开始双方即为平等的,既可以发也可以接,也可以通过数据报包指定不同的地址群发
               //这里是客户端/发送方使用8888端口向 本机地址:9999端口发送数据报包

               ds.send(dp);

               /*
               ByteArrayOutputStream baos = new ByteArrayOutputStream();
               DataOutputStream dos = new DataOutputStream(baos);
                 发送基本数据类型,先将基本数据写入数组,再将数组封包,发送
               dos.writeLong(1000L);
               dos.writeChar('a');
               dos.writeUTF("接收方也需要按写入的顺序读取各个数据类型");
               dos.flush();
               byte[] data2 = baos.toByteArray();
               ds.send(new DatagramPacket(data2,data2.length,new InetSocketAddress("127.0.0.1",9999)));
               */


           } catch (IOException e) {
               throw new RuntimeException(e);
           }
       } catch (UnknownHostException e) {
           throw new RuntimeException(e);
       }
   }
}

class Person implements Serializable{
   //使用UDP发送对象,要发送的对象必须实现Serializable接口
   String name;
   int age;

   public Person(String name, int age) {
       this.name = name;
       this.age = age;
   }
   @Override
   public String toString() {
       return "Person{" +
               "name='" + name + '\'' +
               ", age=" + age +
               '}';
   }
}
class SendObject{
   public static void main(String[] args) {
       Person p = new Person("qian",20);
       byte[] obj = null;
       try(ByteArrayOutputStream baos = new ByteArrayOutputStream();
           ObjectOutputStream oos = new ObjectOutputStream(baos)) {
           oos.writeObject(p);
           oos.flush();
           obj = baos.toByteArray();
       } catch (IOException e) {
           throw new RuntimeException(e);
       }
       DatagramPacket dp = new DatagramPacket(obj,obj.length,new InetSocketAddress("127.0.0.1",9999));
       try(DatagramSocket ds = new DatagramSocket(8888)) {
           ds.send(dp);
       } catch (IOException e) {
           throw new RuntimeException(e);
       }
       //接收方也需要有这个类才能使用ObjectInputStream正确读取
   }
}

javaUDP协议DatagramPacket、DatagramSocket的评论 (共 条)

分享到微博请遵守国家法律