• JAVA深化篇_38—— UDP通信的实现和项目案例


    UDP通信的实现和项目案例

    UDP通信实现原理

    UDP协议与之前讲到的TCP协议不同,是面向无连接的,双方不需要建立连接便可通信。UDP通信所发送的数据需要进行封包操作(使用DatagramPacket类),然后才能接收或发送(使用DatagramSocket类)。

    DatagramPacket:数据容器(封包)的作用

    此类表示数据报包。 数据报包用来实现封包的功能。

    常用方法:

    方法名使用说明
    DatagramPacket(byte[] buf, int length)构造数据报包,用来接收长度为 length 的数据包
    DatagramPacket(byte[] buf, int length, InetAddress address, int port)构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号
    getAddress()获取发送或接收方计算机的IP地址,此数据报将要发往该机器或者是从该机器接收到的
    getData()获取发送或接收的数据
    setData(byte[] buf)设置发送的数据

    DatagramSocket:用于发送或接收数据报包

    当服务器要向客户端发送数据时,需要在服务器端产生一个DatagramSocket对象,在客户端产生一个DatagramSocket对象。服务器端的DatagramSocket将DatagramPacket发送到网络上,然后被客户端的DatagramSocket接收。

    DatagramSocket有两种常用的构造函数。一种是无需任何参数的,常用于客户端;另一种需要指定端口,常用于服务器端。如下所示:

    1. DatagramSocket() :构造数据报套接字并将其绑定到本地主机上任何可用的端口。
    2. DatagramSocket(int port) :创建数据报套接字并将其绑定到本地主机上的指定端口。

    常用方法:

    方法名使用说明
    send(DatagramPacket p)从此套接字发送数据报包
    receive(DatagramPacket p)从此套接字接收数据报包
    close()关闭此数据报套接字

    UDP通信编程基本步骤:

    1. 创建客户端的DatagramSocket,创建时,定义客户端的监听端口。
    2. 创建服务器端的DatagramSocket,创建时,定义服务器端的监听端口。
    3. 在服务器端定义DatagramPacket对象,封装待发送的数据包。
    4. 客户端将数据报包发送出去。
    5. 服务器端接收数据报包。

    UDP通信入门案例

    创建服务端

    public class UDPServer {
      public static void main(String[] args) {
        //创建服务端接收数据的DatagramSocket对象
        try(DatagramSocket datagramSocket = new DatagramSocket(9999)){
          //创建数据缓存区
          byte[] b = new byte[1024];
          //创建数据报包对象
          DatagramPacket dp =new DatagramPacket(b,b.length);
          //等待接收客户端所发送的数据
          datagramSocket.receive(dp);
          String str = new String(dp.getData(),0,dp.getLength());
          System.out.println(str);
         }catch(Exception e){
          e.printStackTrace();
         }
       }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    创建客户端

    public class UDPClient {
      public static void main(String[] args) {
        //创建数据发送对象 DatagramSocket,需要指定消息的发送端口
        try(DatagramSocket ds = new DatagramSocket(8888)) {
    
          //消息需要进行类型转换,转换成字节数据类型。
          byte[] b = "打酱油".getBytes();
    
          //创建数据报包装对象DatagramPacket
          DatagramPacket dp = new DatagramPacket(b, b.length, new InetSocketAddress("127.0.0.1", 9999));
    
          //发送消息
          ds.send(dp);
         }catch(Exception e){
          e.printStackTrace();
         }
       }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    UDP协议传递基本数据类型

    创建服务端

    public class BasicDataUDPServer {
        public static void main(String[] args) {
    
            try(DatagramSocket datagramSocket =new DatagramSocket(9999);){
                //创建字节数组缓冲区
                byte[] bytes = new byte[1024];
                //创建datagramPacket存放字节数组类型的数据
                DatagramPacket datagramPacket=new DatagramPacket(bytes,bytes.length);
                //等待客户端传入数据
                datagramSocket.receive(datagramPacket);
                //实现数据类型转换
                try(DataInputStream dataInputStream =new DataInputStream(new ByteArrayInputStream(bytes))){
                    //通过基本数据数据流对象获取传递的数据
                    System.out.println(dataInputStream.readLong());
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    创建客户端

    public class BasicDataUDPClient {
        public static void main(String[] args) {
            //创建发送数据的DatagramSocket对象
            try(DatagramSocket datagramSocket = new DatagramSocket(8856);
                //创建将基本数据类型转换为字节数组的ByteArrayOutputStream对象
                ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
                //创建将基本数据类型写入ByteArrayOutputStream中的数据输出流对象
                DataOutputStream dataOutputStream =new DataOutputStream(byteArrayOutputStream)){
                //要传递的数据
                long data=10000l;
                //写入ByteArrayOutputStream对象
                dataOutputStream.writeLong(data);
                //将基本数据类型转换为字节数组
                byte[] byteArray = byteArrayOutputStream.toByteArray();
                //将字节数组包装到 DatagramPacket中
                DatagramPacket datagramPacket=new DatagramPacket(byteArray,byteArray.length
                , new InetSocketAddress("127.0.0.1",9999));
                //发送数据
                datagramSocket.send(datagramPacket);
    
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    传递自定义对象类型

    创建Person类

    /**
     * 当该对象需要在网络上传输时,一定要实现Serializable接口
     */
    public class Person implements Serializable {
      private String name;
      private int age;
    
    
      public String getName() {
        return name;
       }
    
    
      public void setName(String name) {
        this.name = name;
       }
    
    
      public int getAge() {
        return age;
       }
    
    
      public void setAge(int age) {
        this.age = age;
       }
    
    
      @Override
      public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
       }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    创建服务端

    public class Person {
        public static void main(String[] args) {
            try(DatagramSocket datagramSocket =new DatagramSocket(9999);){
    
                byte[] bytes =new byte[1024];
    
                DatagramPacket datagramPacket =new DatagramPacket(bytes,bytes.length);
                //接收数据
                datagramSocket.receive(datagramPacket);
    
                //数据类型转换
                try (ObjectInputStream ois = new ObjectInputStream(
                        new ByteArrayInputStream(datagramPacket.getData()))){
                    Person person = (Person)ois.readObject();
                    System.out.println(person);
    
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    创建客户端

    public class ObjectTypeClient {
        public static void main(String[] args) {
            try(DatagramSocket datagramSocket =new DatagramSocket();
                ByteArrayOutputStream bos =new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos)){
                //实例化Person对象
                Person person =new Person();
                person.setAge(18);
                person.setName("zhangsan");
                 //写入ByteArrayOutputStream对象
                oos.writeObject(person);
                //将自定义数据类型转换为字节数组类型
                byte[] byteArray = bos.toByteArray();
                //将自定义数据类型包装到DatagramPacket中
                DatagramPacket datagramPacket=new DatagramPacket(byteArray,byteArray.length,
                                                     new InetSocketAddress("127.0.0.1",9999));
                //发送数据
                datagramSocket.send(datagramPacket);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    Mysql的B+树高度计算
    项目部署、
    使用Python绘制二元函数图像
    IDEA断点常用5种方式——条件断点(循环)、回退、表达式执行、中断(不执行后续代码)、指定异常(常用寻找空指针位置)
    关卡二:基于ECharts数据可视化项目
    java锁升级
    作为新人,如何快速融入新团队?用好这8个点
    解决caffe中的python环境安装的问题(补充)
    【leetcode周赛总结】LeetCode第 81 场双周赛(6.25)
    Java数据结构之队列(Queue)
  • 原文地址:https://blog.csdn.net/guojiaqi_/article/details/134347168