首页 > 前沿技术 正文
javaUDP协议DatagramPacket、DatagramSocket

时间:2022-11-27 04:37:23 阅读: 评论: 作者:

  /**

  * 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.s(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.s(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 SObject{

   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.s(dp);

   } catch (IOException e) {

   throw new RuntimeException(e);

   }

   //接收方也需要有这个类才能使用ObjectInputStream正确读取

   }

  }