【Java 网络编程】UDP 服务器 客户端 通信 ( DatagramSocket | DatagramPacket | UDP 发送数据包 | UDP 接收数据包 | 端口号分配使用机制 )

简介: 【Java 网络编程】UDP 服务器 客户端 通信 ( DatagramSocket | DatagramPacket | UDP 发送数据包 | UDP 接收数据包 | 端口号分配使用机制 )

文章目录

I UDP 信息发送接收原理

II UDP 发送和接收端口相同

III UDP 发送信息代码示例

IV UDP 接收信息代码示例

V UDP 服务器端代码示例

VI UDP 客户端代码示例

VII 客户端服务器端通信



I UDP 信息发送接收原理


1. UDP 既有客户端的功能 , 也有服务器端的功能 ;


2. UDP 发送和接收 : 计算机 A 向 计算机 B 的 X 端口发送消息 , B 不一定能接收到 , B 能收到并处理该消息的前提是 , B 当前正在监听 X 端口 ;


3. 发送设备个数 : B 监听 X 端口 , 并接收数据 , 向 B 发送信息的设备可以是多个 , B 可以接收到任何设备向其 X 端口发送的数据 ;


4. 端口号说明 : UDP 报文头 64 位 , 其中有发送源端口号 , 和接收的目标端口号 , 这个目标端口号是 X 端口号 , 发送源端口号是随机的动态端口号 ;


5. 相互通信 : B 收到消息时 , 才知道 A 设备发送消息的端口号 ; 如果 B 收到消息 , 然后马上向 A 的发送源端口号回送一条消息 , 如果 A 计算机正在监听这个端口号 , 就可以收到 B 计算机发送的消息 ; 如果 A 没有监听 , 那么收不到这个消息 ;




II UDP 发送和接收端口相同


UDP 发送和接收使用的是同一个端口 ;

UDP 发送和接收使用的是同一个端口 ;

UDP 发送和接收使用的是同一个端口 ;


重要的事情说三遍




III UDP 发送信息代码示例


1. 创建 DatagramSocket 对象 : 发送 UDP 数据包 , 首先要创建 DatagramSocket 对象 , 该对象可用于 UDP 数据包的发送和接收 , 创建时如果需要监听数据的接收 , 可以指定监听的端口 , 也可以等待系统自动分配一个端口 , 使用该端口进行数据的发送和接收 ;


2. 创建并设置 DatagramPacket 对象 : 发送的数据包实体是 DatagramPacket 对象 , 将目标设备的 IP 地址 , 端口号 , 发送的 byte[] 数组数据 , 设置到该数据包实体中 , 调用 DatagramSocket 对象的 send 方法 , 将该数据包发送出去 ;


3. 动态端口号自动分配 : 这里注意 , 发送的同时 , 系统自动分配了 一个动态端口号 , 该发送端口号就是接受端口号 , UDP 开始监听该端口号 , 意味着可以从该端口号接受数据包 , 服务器端就是接收到信息后 , 将反馈数据发送到该动态分配的端口中 ;


       

//I. 创建 DatagramSocket 对象 , 用于 UDP 数据包的发送和接收
            //1. UDP 数据包套接字 , 客户端 ,
            //      无需指定端口 , 让系统直接分配一个端口 , 使用该端口发送和接收数据
            DatagramSocket datagramSocket = new DatagramSocket();
            //II. 发送 UDP 数据包
            //2. 客户端发送给服务器端的端口号
            String sendMessage = "你好, 服务器 !";
            //3. 将字符串转为 byte[] 数组
            byte[] sendData = sendMessage.getBytes();
            //4. 创建发送数据包 , 需要传入的参数 1> 数据 2> 数据长度 3> 接收者的地址 4> 接收者的端口号
            //      向服务器端发送数据 , 发送的端口是自动分配的
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
                    InetAddress.getLocalHost(), 8888);
            //5. 将数据包发送出去
            datagramSocket.send(sendPacket);



IV UDP 接收信息代码示例


1. 创建 DatagramSocket 对象 : 接收 UDP 数据包 , 首先要创建 DatagramSocket 对象 , 注意必须设置一个监听的端口号 , 才能接收数据包 ;


客户端没有设置监听端口号 , 接收到了数据 , 是因为其先发送的数据 , 发送数据的同时 , 系统自动为其分配了一个动态端口号 , UDP 中发送和接收使用的是同一个端口号 , 在分配完该动态端口号之后 , 客户端就开始监听该端口号了 ;


2. 创建并设置 DatagramPacket 对象 : 接收的数据包实体是 DatagramPacket 对象 , 需要为其设置一个接收数据的缓冲区 , 接收到数据包后 , 系统会自动将发送信息的设备的 IP 地址 , 端口号 , 发送的 byte[] 数组数据 , 设置到该数据包实体中 , 调用 DatagramSocket 对象的 receive 方法 , 会阻塞等待数据包到来 ;


     

//I. 创建 DatagramSocket 对象 , 用于 UDP 数据包的发送和接收
            //1. UDP 数据包接收者 , 监听 8888 端口
            //      该 DatagramSocket 既可以接收数据包 , 也可以发送数据包
            DatagramSocket datagramSocket = new DatagramSocket(8888);
            //II. 接收 UDP 数据包
            //2. 接收数据包使用的缓冲区
            byte[] receiveBuffer = new byte[1024];
            //3. 接收 UDP 数据包使用的 DatagramPacket 对象
            DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
            //4. 接收 UDP 数据包
            datagramSocket.receive(receivePacket);



V UDP 服务器端代码示例


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPServer {
    public static void main(String[] args){
        try {
            System.out.println("服务器 开始运行");
            //I. 创建 DatagramSocket 对象 , 用于 UDP 数据包的发送和接收
            //1. UDP 数据包接收者 , 监听 8888 端口
            //      该 DatagramSocket 既可以接收数据包 , 也可以发送数据包
            DatagramSocket datagramSocket = new DatagramSocket(8888);
            //II. 接收 UDP 数据包
            //2. 接收数据包使用的缓冲区
            byte[] receiveBuffer = new byte[1024];
            //3. 接收 UDP 数据包使用的 DatagramPacket 对象
            DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
            //4. 接收 UDP 数据包
            datagramSocket.receive(receivePacket);
            //5. 获取发送端的 IP 地址
            String sendIP = receivePacket.getAddress().getHostAddress();
            //6. 获取发送端的端口号
            int sendPort = receivePacket.getPort();
            //7. 获取接收到的数据的长度
            int receiveLen = receivePacket.getLength();
            //8. 获取接收到的数据 , 并转为字符串
            String receiveData = new String(receivePacket.getData(), 0, receiveLen);
            //9. 打印接收到的数据包信息
            System.out.println("服务器 接收到 " + sendIP + " : " + sendPort + " 发送的数据 : " + receiveData);
            //III. 发送 UDP 数据包
            //10. 将接收到的数据长度回送给发送者
            String response = "服务器端 收到客户端发送的 " + receiveLen + " Byte 数据";
            //11. 将字符串转为 byte[] 数组
            byte[] responseData = response.getBytes();
            //12. 创建发送数据包 , 需要传入的参数 1> 数据 2> 数据长度 3> 接收者的地址 4> 接收者的端口号
            DatagramPacket responsePacket = new DatagramPacket(responseData, responseData.length,
                    receivePacket.getAddress(), receivePacket.getPort());
            //13. 将数据包发送出去
            datagramSocket.send(responsePacket);
            System.out.println("服务器 向客户端 " + sendIP + " : " + sendPort + " 发送的数据 : " + response);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("服务器 运行结束");
        }
    }
}



VI UDP 客户端代码示例


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UDPClient {
    public static void main(String[] args){
        try {
            System.out.println("客户端 开始运行");
            //I. 创建 DatagramSocket 对象 , 用于 UDP 数据包的发送和接收
            //1. UDP 数据包套接字 , 客户端 ,
            //      无需指定端口 , 让系统直接分配一个端口 , 使用该端口发送数据
            DatagramSocket datagramSocket = new DatagramSocket();
            //II. 发送 UDP 数据包
            //2. 客户端发送给服务器端的端口号
            String sendMessage = "你好, 服务器 !";
            //3. 将字符串转为 byte[] 数组
            byte[] sendData = sendMessage.getBytes();
            //4. 创建发送数据包 , 需要传入的参数 1> 数据 2> 数据长度 3> 接收者的地址 4> 接收者的端口号
            //      向服务器端发送数据 , 发送的端口是自动分配的
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
                    InetAddress.getLocalHost(), 8888);
            //5. 将数据包发送出去
            datagramSocket.send(sendPacket);
            System.out.println("客户端 向服务器 : " +
                    InetAddress.getLocalHost() + " : " + 8888 + " 发送的数据 : " + sendMessage);
            //III. 接收 UDP 数据包
            //6. 接收数据包使用的缓冲区
            byte[] receiveBuffer = new byte[1024];
            //7. 接收 UDP 数据包使用的 DatagramPacket 对象
            DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
            //8. 接收 UDP 数据包
            datagramSocket.receive(receivePacket);
            //9. 获取发送端的 IP 地址
            String sendIP = receivePacket.getAddress().getHostAddress();
            //10. 获取发送端的端口号
            int sendPort = receivePacket.getPort();
            //11. 获取接收到的数据的长度
            int receiveLen = receivePacket.getLength();
            //12. 获取接收到的数据 , 并转为字符串
            String receiveData = new String(receivePacket.getData(), 0, receiveLen);
            //13. 打印接收到的数据包信息
            System.out.println("客户端 接收到服务器端反馈信息 : " +
                    sendIP + " : " + sendPort + " 发送的数据 : " + receiveData);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("客户端 运行结束");
        }
    }
}





VII 客户端服务器端通信


1. 服务器运行 : 先运行服务器 , 此时服务器开始监听 8888 端口 ,


2. 客户端发送信息 : 再运行客户端 , 客户端向服务器端的 8888 端口发送数据 , 客户端的发送端口是随机的 , 本次是 57660 端口 , 这是个动态分配端口 , UDP 的发送和接收端口是同一个端口 , 此时 UDP 开始监听该端口 ;


3. 服务器端反馈信息 : 服务器端收到客户端发送的数据 , 处理后将反馈数据再次发送回去 , 这里发送给客户端的 57660 端口 , 服务器端的发送端口就是 8888 端口 ;


UDP 发送和接收端口是同一个端口 ;

image.png



目录
相关文章
|
安全 网络安全 数据安全/隐私保护
访问控制列表(ACL)是网络安全中的一种重要机制,用于定义和管理对网络资源的访问权限
访问控制列表(ACL)是网络安全中的一种重要机制,用于定义和管理对网络资源的访问权限。它通过设置一系列规则,控制谁可以访问特定资源、在什么条件下访问以及可以执行哪些操作。ACL 可以应用于路由器、防火墙等设备,分为标准、扩展、基于时间和基于用户等多种类型,广泛用于企业网络和互联网中,以增强安全性和精细管理。
2164 7
|
Python
使用Python实现multipart/form-data文件接收的http服务器
至此,使用Python实现一个可以接收 'multipart/form-data' 文件的HTTP服务器的步骤就讲解完毕了。希望通过我的讲解,你可以更好地理解其中的逻辑,另外,你也可以尝试在实际项目中运用这方面的知识。
600 69
|
11月前
|
应用服务中间件 网络安全 数据安全/隐私保护
网关服务器配置指南:实现自动DHCP地址分配、HTTP服务和SSH无密码登录。
哇哈哈,道具都准备好了,咱们的魔术秀就要开始了。现在,你的网关服务器已经魔法满满,自动分配IP,提供网页服务,SSH登录如入无人之境。而整个世界,只会知道效果,不会知道是你在幕后操控一切。这就是真正的数字世界魔法师,随手拈来,手到擒来。
501 14
|
缓存 应用服务中间件 nginx
Web服务器的缓存机制与内容分发网络(CDN)
【8月更文第28天】随着互联网应用的发展,用户对网站响应速度的要求越来越高。为了提升用户体验,Web服务器通常会采用多种技术手段来优化页面加载速度,其中最重要的两种技术就是缓存机制和内容分发网络(CDN)。本文将深入探讨这两种技术的工作原理及其实现方法,并通过具体的代码示例加以说明。
1148 1
|
机器学习/深度学习 编解码 移动开发
YOLOv11改进策略【Conv和Transformer】| TPAMI-2024 Conv2Former 利用卷积调制操作和大核卷积简化自注意力机制,提高网络性能
YOLOv11改进策略【Conv和Transformer】| TPAMI-2024 Conv2Former 利用卷积调制操作和大核卷积简化自注意力机制,提高网络性能
536 7
YOLOv11改进策略【Conv和Transformer】| TPAMI-2024 Conv2Former 利用卷积调制操作和大核卷积简化自注意力机制,提高网络性能
|
网络协议 Java Shell
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
1017 7
|
网络协议 Java 应用服务中间件
深入浅出Tomcat网络通信的高并发处理机制
【10月更文挑战第3天】本文详细解析了Tomcat在处理高并发网络请求时的机制,重点关注了其三种不同的IO模型:NioEndPoint、Nio2EndPoint 和 AprEndPoint。NioEndPoint 采用多路复用模型,通过 Acceptor 接收连接、Poller 监听事件及 Executor 处理请求;Nio2EndPoint 则使用 AIO 异步模型,通过回调函数处理连接和数据就绪事件;AprEndPoint 通过 JNI 调用本地库实现高性能,但已在 Tomcat 10 中弃用
深入浅出Tomcat网络通信的高并发处理机制
|
网络协议 Ubuntu Linux
gpg从公钥服务器接收失败(gpg: keyserver receive failed: Server indicated a failure)
通过上述步骤,大多数情况下应该能够解决GPG从公钥服务器接收失败的问题。如果问题依旧存在,可能需要进一步调查与公钥服务器相关的更深层次的技术问题,或者考虑在相关社区论坛寻求帮助。
3813 1
|
数据安全/隐私保护
Haskell网络编程:代理服务器的高级使用技巧
Haskell网络编程:代理服务器的高级使用技巧