• 14.Java实现UDP通信


    1.关键API

    java.net包里提供了实现网络应用程序的类。
    在Java中,我们可以使用DatagramSocket来创建UDP服务器,使用DatagramPacket来装载接受的数据。
    DatagramSocket这个类是用来发送和接收数据包的套接字类。

    发送数据包用的方法是: DatagramSocket.send(DatagramPacket p)
    接收数据包用的方法是: DatagramSocket.receive(DatagramPacket p)
    
    • 1
    • 2

    DatagramPacket这个类是用来存储数据的数据包。
    一般的用法如下:

    //其中data是数据字节数组,address是目标地址,port是目标端口号
    DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
    
    • 1
    • 2

    1.1 UDP报文格式

    首先要知道UDP是一种无连接的传输层协议。与TCP不同的是,UDP不保证数据完整无误的发送给目标,而是通过IP层的最大努力机制来传递数据的。

    每个UDP报文分别由UDP报文头和UDP数据区两部分组成。
    其中UDP报文头有8个字节:
    源端口(2字节)+目的端口(2字节)+报文长度(2字节)+校验值(2字节)
    UDP数据区长度可变,根据报文长度不同而不同。
    在这里插入图片描述

    2.实例Demo

    2.1 UDPServer

    package InternetCode.Udp;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.util.Scanner;
    
    /*
     * 服务器端,实现基于UDP的用户登陆
     */
    public class UDPServer {//公共类
        public static void main(String[] args) throws IOException {//主程序入口
            /*
             * 接收客户端发送的数据
             */
            // 1.创建服务器端DatagramSocket,指定端口
            DatagramSocket socket = new DatagramSocket(8800);
            // 2.创建数据报,用于接收客户端发送的数据
            byte[] data = new byte[1024];//创建字节数组,指定接收的数据包的大小
            DatagramPacket packet = new DatagramPacket(data, data.length);
    
            // 3.接收客户端发送的数据
            System.out.println("****服务器端已经启动,等待客户端发送数据");//输出提示信息
            //通过循环不停的向客户接收数据
            new Thread(()->{
                while(true) {
                    try {
                        socket.receive(packet);// 此方法在接收到数据报之前会一直阻塞
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    // 4.读取数据
                    String info = new String(data, 0, packet.getLength());//创建字符串对象
                    System.out.println("我是服务器,客户端说:" + info);//输出提示信息
    
                }
            }).start();
    
            final InetAddress[] address = {null};
            final int[] port = {0};
            final boolean[] flag = {false};
            //向客户端发送信息
            new Thread(()->{
            while (true){
                if(!flag[0]){
                    // 1.定义客户端的地址、端口号、数据
                    address[0] = packet.getAddress();//获取发送端的地址
                    port[0] = packet.getPort();//获取 发送端进程所绑定的端口
                    flag[0] = true;
                }
                Scanner scanner = new Scanner(System.in);//从键盘接受数据
                String send = scanner.nextLine();//nextLine方式接受字符串
                byte[] data2 = send.getBytes();//将接收到的数据转换为字节数组
                DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address[0], port[0]);// 2.创建数据报,包含响应的数据信息
                try {
                    socket.send(packet2); // 3.响应客户端
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            }).start();
        }
    }
    
    • 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
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    2.2 UDPClient

    package InternetCode.Udp;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.util.Scanner;
    /*
     * 客户端
     */
    public class UDPClient {//公共类
        public static void main(String[] args) throws IOException {//主程序入口
            /*
             * 向服务器端发送数据
             */
            // 1.定义服务器的地址、端口号、数据
            InetAddress address = InetAddress.getByName("localhost");
            int port = 8800;//定义端口类型
            DatagramSocket socket = new DatagramSocket();
    
            new Thread(()->{
                while(true) {
                    //通过循环不同的向客户端发送和接受数据
                    Scanner scanner = new Scanner(System.in);//从键盘接受数据
                    String send = scanner.nextLine();//nextLine方式接受字符串
                    byte[] data = send.getBytes();//将接收到的数据变成字节数组
    
                    //2.创建数据报,包含发送的数据信息
                    DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
                    // 3.创建DatagramSocket对象
                    try {
                        socket.send(packet);// 4.向服务器端发送数据报
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
    
                }
            }).start();
    
            new Thread(()->{
                while (true){
                    /*
                     * 接收服务器端响应的数据
                     */
                    byte[] data2 = new byte[1024];//创建字节数组
                    DatagramPacket packet2 = new DatagramPacket(data2, data2.length);// 1.创建数据报,用于接收服务器端响应的数据
                    try {
                        socket.receive(packet2);// 2.接收服务器响应的数据
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    //3.读取数据
                    String reply = new String(data2, 0, packet2.getLength());//创建字符串对象
                    System.out.println("我是客户端,服务器说:" + reply);//输出提示信息
                }
            }).start();
    
        }
    }
    
    • 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
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    运行结果如下:
    在这里插入图片描述

    借鉴文章:https://blog.csdn.net/qq_41182503/article/details/80179961

  • 相关阅读:
    【好文转载】曲线的切向量怎么求?和平面法向量的联系
    前端面试话术集锦第 12 篇:高频考点(Vue常考基础知识点)
    深度分析自媒体短视频运营播放少,涨粉难的原因
    【算法】最短路径——迪杰斯特拉 (Dijkstra) 算法
    C#上位机与PLC
    基于Spark的K-means快速聚类算法的优化
    LQ0045 煤球数目【迭代】
    zabbix部署与监控
    OpenText EnCase 客户案例——哥伦比亚总检察长办公室建立值得信赖的司法警察服务
    图扑软件荣获第七届“创客中国”中小企业创新创业大赛优胜奖!
  • 原文地址:https://blog.csdn.net/c1776167012/article/details/126006934