• 计算机网络(第三弹) --- UDP 套接字编程的通信模型及实现流程


      对于 UDP 协议来说, 具有无连接, 面向数据报的特征, 因此每次都是没有建立连接, 并且一次性发送全部数据报, 一次性接收全部的数据报; java 中使用 UDP 协议通信主要基于 DatagramSocket 类来创建数据报套接字, 并使用 DatagramPacket 作为发送或接收的 UDP 数据报.

    1 数据报套接字通信流程

    对于 UDP 协议来说, 具有无连接, 面向数据报的特征, 因此每次都是没有建立连接, 并且一次性发送全部数据报, 一次接收全部的数据报; java 中使用 UDP 协议通信主要基于 DatagramSocket 类来创建数据报套接字, 并使用 DatagramPacket 作为发送或接收的 UDP 数据报, 对于一个服务端而言, 重要的是提供多个客户端的请求处理及相应, 主要流程如下:
    在这里插入图片描述

    2 编程实现

    2.1 服务器端代码实现

    服务器端代码如下:

    public class UdpEchoServer {
        private DatagramSocket socket = null;
        public UdpEchoServer(int port) throws SocketException {
            socket = new DatagramSocket(port);
        }
    
        public void start() throws IOException {
            System.out.println("服务器启动!");
            while(true) {
                DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
                socket.receive(requestPacket);
                String request = new String(requestPacket.getData(),
                        0, requestPacket.getLength()).trim();
                String response = process(request);
                DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),
                        response.getBytes().length,requestPacket.getSocketAddress());
                socket.send(responsePacket);
    
                System.out.printf("[%s:%d] req: %s; resp: %s\n",requestPacket.getAddress().toString(),
                        requestPacket.getPort(),request,response);
            }
        }
    
        public String process(String request) {
            return request;
        }
    
        public static void main(String[] args) throws IOException {
            UdpEchoServer server = new UdpEchoServer(9090);
            server.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

    流程解读:
    在这里插入图片描述

    2.2 客户端代码实现

    public class UdpEchoClient {
        private DatagramSocket socket = null;
        private String serverIp;
        private int serverPort;
    
        public UdpEchoClient(String serverIp,int serverPort) throws SocketException {
            this.serverIp = serverIp;
            this.serverPort = serverPort;
            socket = new DatagramSocket();
        }
    
        public void start() throws IOException {
            Scanner scanner = new Scanner(System.in);
            while(true) {
                System.out.print("-->");
                String request = scanner.nextLine();
                if(request.equals("exit" +
                        "")) {
                    break;
                }
                
                DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),
                        request.getBytes().length, InetAddress.getByName(serverIp),serverPort);
                socket.send(requestPacket);
    
                DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096 );
                socket.receive(responsePacket);
                String response = new String(responsePacket.getData(),0,responsePacket.getLength());
    
                System.out.println(response);
            }
        }
    
        public static void main(String[] args) throws IOException {
            UdpEchoClient client = new UdpEchoClient("127.0.0.1",9090);
            client.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

    代码流程解读:
    在这里插入图片描述

    2.3 运行结果

    在这里插入图片描述

    2.4 整体逻辑

    在这里插入图片描述

    2.5 注意事项

    • DatagramPacket 是 UDP socket 发送和接收数据的基本单位, socket 对象本质上是一个文件, 这个文件是网卡的抽象, 可以理解为 “一切皆文件”;
    • 再次强调 IP 是用来决定互联网上的某个主机的位置, port 是决定数据交给这个主机上的哪个程序, 这里的关系不是 “一一对应” 的关系, 只是要配合使用, 同一个 IP 上面的 n 个服务器程序就有 n 个端口号;
    • 程序启动之后, 马上就能执行到 receive 操作, 服务器启动之后, 客户端并没有接着发送请求, 客户端什么时候发送请求并不能确定, 大概率的情况是调用 receive 的时候客户端还没发任何数据, 此时的 receive 操作就会阻塞, 一直阻塞到真的有数据过来为止, 此处的阻塞时间完全不可预期; 当真的有客户端传过数据来的时候, 此时的 receive 就会把收到的数据放到 DatagramPacket 对象的缓冲区中.
  • 相关阅读:
    docker安装网易云音乐(yesplaymusic)
    【深度学习】Transformer、GPT、BERT、Seq2Seq什么区别?
    计算机网络第八章知识点回顾(自顶向下)
    Window Server 2016 FTP用户隔离和磁盘配额部署
    2022阿里巴巴全球数学竞赛 第4题 虎虎生威(盲盒问题、集卡问题)解决思路
    Uniapp软件库源码 全新带勋章功能(包含前后端源码)
    【JavaSE】之多态
    基于stm32f103系列的简单软件I2C和硬件I2C通讯
    FPGA高端项目:图像采集+GTP+UDP架构,高速接口以太网视频传输,提供2套工程源码加QT上位机源码和技术支持
    [MT8766][Android12] 使用谷歌LPA实现ESIM功能的流程
  • 原文地址:https://blog.csdn.net/Onion_521257/article/details/127812100