UDP协议详解+代码演示

1、UDP协议基础

1. UDP是什么?

UDP(User Datagram Protocol,用户数据报协议)是传输层的核心协议之一,与TCP并列。它的主要特点是:​​​​

  • 无连接:通信前不需要建立连接(知道对端的IP和端口号就直接进行传输,不需要建立连接)

  • 不可靠:不保证数据包的顺序、完整性或可达性(没有确认机制,没有重传机制;如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息)

  • 大小受限:⼀次最多传输64k(UDP协议首部中有⼀个16位的最大长度.也就是说⼀个UDP能传输的数据最大长度是 64K(包含UDP首部))

  • 轻量级:头部开销小(仅8字节)

  • 高效:没有TCP的握手、确认和重传机制

2. UDP报文结构

UDP数据包(称为数据报)由头部和数据部分组成:

  • 源端口号(2字节):发送方端口

  • 目标端口号(2字节):接收方端口

  • 数据报长度(2字节):头部+数据的长度

  • 校验和(2字节):错误检测(可选)如果校验和出错则直接丢弃

2、UDP的核心特性

1. 无连接通信:UDP不需要预先建立连接,直接发送数据报。这类似于寄信,不需要确认收件人是否在家。

2. 不可靠传输:UDP不提供:数据包确认机制、丢失重传机制、数据包排序功能

3.面向数据报:每个UDP数据报都是独立的,这与TCP的字节流模式不同

4.支持广播和多播:UDP可以向多个主机同时发送数据:

  • 单播 :一对一

  • 广播 :一对所有

  • 多播 :一对一组

3、基于UDP的应用层协议

  • NFS:网络文件系统
  • TFTP:简单文件传输协议
  • DHCP:动态主机配置协议
  • BOOTP:启动协议(用于无盘设备启动)
  • DNS:域名解析协议

当然,也包括我们自己写UDP程序时自定义的应用层协议。

4、Java中的UDP编程

主要使用了两个类 :

1、DatagramSocket :用于发送和接收数据报的套接字

// 创建UDP套接字(绑定随机端口)
DatagramSocket socket = new DatagramSocket();

// 创建绑定特定端口的套接字
DatagramSocket serverSocket = new DatagramSocket(8080);

2、DatagramPacket :表示UDP数据报的容器

// 创建接收数据包
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

// 创建发送数据包
String message = "Hello UDP";
byte[] data = message.getBytes();
DatagramPacket sendPacket = new DatagramPacket(
    data, 
    data.length, 
    InetAddress.getByName("localhost"), 
    8080
);

5、完整Java UDP示例

1.Echoserver:UDP服务器,接收客户端消息并原样返回

package Network.UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class Echoserver {//创建一个socket对象private DatagramSocket socket;//构造方法,初始化socket对象public Echoserver(int port) throws SocketException {socket = new DatagramSocket(port);}//启动服务器,完成主要的业务逻辑public void start() throws IOException {System.out.println("服务器启动!");while(true) {//1.接收客户端的请求并解析//1)创建一个字节数组(DatagramPacket 对象),用于存储接收到的数据DatagramPacket reqPacket = new DatagramPacket(new byte[4096],4096);//2)通过receive读取网卡的数据,如果网卡没有收到数据,就会阻塞等待socket.receive(reqPacket);//3)把DATagramPacket中的数据解析成字符串,只需要从DatagramPacket取到有效的树即可String request = new String(reqPacket.getData(),0,reqPacket.getLength());//2.根据请求计算响应String response = process(request);//3.把响应写回客户端//1)把响应字符串转成字节数组,并封装成DatagramPacket对象DatagramPacket resPacket = new DatagramPacket(response.getBytes(),response.getBytes().length,reqPacket.getSocketAddress());//2)通过socket把DatagramPacket对象发送出去 (把DatagramPacket写回到客户端)socket.send(resPacket);//4.打印日志System.out.printf("[%s:%d] req: %s,resp: %s\n",reqPacket.getAddress(),reqPacket.getPort(),request,response);}}//由于是“回显服务器”,所以响应和请求是一样的,直接返回请求即可public String process(String request) {return request;}public static void main(String[] args) throws IOException {Echoserver server = new Echoserver(9090);server.start();          //回显服务器完成}
}

代码详细解析:

①创建 EchoServer 服务端的类,定义成员变量

  • DatagramSocket:UDP通信的核心类,用于发送和接收数据报

  • 封装在类中作为成员变量,整个生命周期内有效


②构造方法

  • 创建绑定到指定端口的 DatagramSocket(可能会抛出异常,如:该端口已被占用)

  • port 是服务器自身绑定的监听端口号,等待客户端发送数据,客户端需要知道服务器的这个端口号才能向其发送消息。

  • 客户端通过该端口找到服务器,而客户端的端口由系统动态分配。

  • 这种设计体现了 UDP 无连接的特性,服务器只需关注自身绑定端口即可接收所有客户端消息。


③核心业务逻辑(start方法)

  • while 无限循环接收来自客户端的数据,这里可以根据自己的需求更改接收次数
  • 创建缓冲区:分配一个4096字节(字节大小自行定义不溢出就行)的空数组,存储接收到的数据
  • 阻塞等待数据报到达(数据此时已存入 reqPacket 的字节数组中)如果 reqPacket 没有接收到客户端发来的数据这里会阻塞等待
  • 声明 String 类型的 request 变量,将 reqPacket 中的数据解析为字符串
  1. getData() :获取字节数组(可能包含多余的空字节)
  2. getLength() :获取实际有效数据长度(避免解析无效字节)

在网络编程中,将响应(response)转成字节数组(byte[])再发送是必要的步骤,这与计算机底层的数据传输机制和网络协议的特性密切相关。

  • process() :返回响应后的数据,由于整段代码实现的是 Echo(回显) 服务器代码,响应内容=请求内容,所以方法中直接返回请求即可
  • soclet.send() :将数据发送回客户端

附上发送回客户端的终端代码

  • 打印日志:打印客户端信息和通信内容


④主方法

  • new Echoserver(9090) :调用构造函数,创建绑定到 9090 端口的 DatagramSocket(UDP套接字)

  • server.start() :启动服务器循环,等待客户端数据报



2.EchoClient:UDP客户端,发送消息并显示服务器返回的响应

package Network.UDP;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;public class EchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;public EchoClient(String serverIp, int serverPort) throws IOException {  socket = new DatagramSocket();this.serverIp = serverIp;this.serverPort = serverPort;}   //启动客户端,发送数据,接收数据,关闭连接public void start() throws IOException {Scanner scanner = new Scanner(System.in);System.out.println("客户端启动!");while(true) {//1.从控制台读取要发送的数据内容(用字符串表示)System.out.print(">");String request = scanner.nextLine(); //2.构造成UDP请求,并发送.不光要填内容,还要填服务器的地址和端口号DatagramPacket reqPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIp),serverPort); socket.send(reqPacket);//3.接收服务器响应的数据DatagramPacket resPacket = new DatagramPacket(new byte[4096], 4096);socket.receive(resPacket);String response = new String(resPacket.getData(),0,resPacket.getLength());//4.把响应的数据解析并打印System.out.println(response);}}public static void main(String[] args) throws IOException {EchoClient echoclient = new EchoClient("127.0.0.1",9090);echoclient.start();}
}

详细代码解析:

①创建 EchoClient 客户端的类,定义成员变量

  • socket :客户端UDP套接字

  • serverIp/serverPort :服务器地址信息

 


②构造方法

  • DatagramSocket ( )  为客户端随机分配一个端口号
  • 保存服务器地址信息


③核心业务逻辑(start方法)

  • request 用户输入要发送的数据
  • reqPacket 封装要发送的数据
  1. request.getBytes() :将用户输入的字符串转换为字节数组
  2. request.getBytes().length :获取字节数组的长度,表示要发送的数据大小
  3. InetAddress.getByName(serverIp) :通过服务器的IP地址获取对应的 InetAddress 对象,表示数据要发送到的目标地址
  4. serverPort :服务器的端口号,表示数据要发送到的端口
  • socket.send() :调用 send 方法将数据报发送到指定的目标地址和端口
  • resPacket() :接收服务器发回的响应数据,socket.receive() 是一个阻塞操作,直到接收到数据才会继续执行
  • response :提取响应内容,将接收到的字节数据转换为字符串

④主方法

  • 创建客户端实例,连接本地服务器的9090端口
  • start 启动客户端

6、UDP编程注意事项

1.数据报大小限制

  • UDP数据报最大长度理论为65535字节
  • 实际受MTU限制(通常1500字节)
  • 建议保持数据报在1472字节以内(IPv4)

2.数据边界问题

  • 每个 receive() 调用接收一个完整的数据报
  • 不会出现TCP的“粘包”问题

3.错误处理

  • 网络不可达
  • 端口未监听
  • 数据包丢失

4.安全性考虑

  • UDP易受DDoS攻击
  • 应考虑实现应用层的验证机制

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/77557.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于大模型的胆总管结石全流程预测与临床应用研究报告

目录 一、引言 1.1 研究背景 1.2 研究目的与意义 1.3 研究方法和创新点 二、大模型在胆总管结石预测中的应用原理 2.1 大模型概述 2.2 模型构建的数据来源与处理 2.3 模型训练与优化 三、术前预测与准备 3.1 术前胆总管结石存在的预测 3.2 基于预测结果的术前检查方…

Windows避坑部署SkyworkAI/SkyReels-V2昆仑万维电影生成模型

#工作记录 前言 SkyworkAI/SkyReels-V2 是由昆仑万维开源的全球首个无限时长电影生成模型,基于扩散强迫框架结合多模态大语言模型、强化学习等技术,支持文本到视频、图像到视频等多种生成方式 开源项目地址: SkyworkAI/SkyReels-V2&#x…

iVX 图形化编程如何改写后端开发新范式

在数字化转型加速推进的当下,企业对后端系统的需求呈现爆发式增长。Gartner 最新报告指出,2025 年全球企业平均需完成 300 定制化应用开发,而传统编码模式下,单个项目平均交付周期长达 6 - 8 个月。与此同时,Redis、K…

策略模式:灵活的算法封装与切换

策略模式是一种行为型设计模式,它将一组算法封装成独立的类,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端。本文将以一个收银系统为例,详细介绍策略模式的实现和应用。 什么是策略模式? 策略模式定义了算法…

第十四章-PHP与HTTP协议

第十四章-PHP与HTTP协议 一,HTTP 协议详解 HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最广泛的协议之一,用于客户端(如浏览器)与服务器之间的通信。它是 Web 技术的基石…

刀客独家 | 潘胜接管百度移动生态市场部

一、 据刀客doc向独家信源确认,百度移动生态事业群(MEG)市场部日前完成重要人事调整:潘胜已经接任市场负责人。 此前,根据雷锋网3月底的报道,百度云渠道生态总经理陈之若离职,原移动生态事业群…

Springoot、Flowable快速学习

应用背景: 公司打算做个考勤系统,涉及到请假、补卡之类的流程审批。想到了工作流,gitee、github上看了下开源的,有自研的和常见的Flowable‌、Activiti‌。首先放弃自研的,考虑到成熟度、社区生态,最后选择…

关于 【Spring Boot Configuration Annotation Processor 未配置问题】 的详细分析、解决方案及代码示例

以下是关于 Spring Boot Configuration Annotation Processor 未配置问题 的详细分析、解决方案及代码示例: 1. 问题描述 当使用 Spring Boot 的配置注解(如 ConfigurationProperties、Value、ConditionalOnProperty 等)时,若未…

Spring系列四:AOP切面编程 第一部分

AOP切面编程 💗AOP-官方文档🍝AOP 讲解🍝AOP APIs 💗动态代理🍝初探动态代理🍝动态代理深入🍝AOP问题提出📗使用土方法解决📗 对土方法解耦-开发最简单的AOP类&#x1f4…

【云计算】云计算中IaaS、PaaS、SaaS介绍

0 随着云计算、大数据、人工智能发展迅速,布局“云”已经是互联网企业共识。云计算的服务类型分为三种,分别为IaaS、PaaS、SaaS,这三个分别是什么意思,今天做一个简单的介绍和了解。 一、云计算 云计算是用户需求通过Internet获取计算资源,把计算资源包装成服务,提供给…

使用HYPRE库并行装配IJ稀疏矩阵指南: 矩阵预分配和重复利用

使用HYPRE库并行装配IJ稀疏矩阵指南 HYPRE是一个流行的并行求解器库,特别适合大规模稀疏线性系统的求解。下面介绍如何并行装配IJ格式的稀疏矩阵,包括预先分配矩阵空间和循环使用。 1. 初始化矩阵 首先需要创建并初始化一个IJ矩阵: #incl…

目标跟踪最新文章阅读列表

AAAI2025 TrackFormer: Multi-Object Tracking with Transformers 论文:https://arxiv.org/abs/2101.02702 代码:https://github.com/timmeinhardt/trackformer AAAI2025 SUTrack 单目标跟踪 论文:https://pan.baidu.com/s/10cR4tQt3lSH5V2RNf7-3gg?pwd=pks2 代码:htt…

分布式GPU上计算长向量模的方法

分布式GPU上计算长向量模的方法 当向量分布在多个GPU卡上时,计算向量模(2-范数)需要以下步骤: 在每个GPU上计算本地数据的平方和跨GPU通信汇总所有平方和在根GPU上计算总和的平方根 实现方法 下面是一个完整的CUDA示例代码,使用NCCL进行多…

高并发下单库存扣减异常?飞算 JavaAI 自动化生成分布式事务解决方案

在电商、旅游等行业业务量激增,高并发下单场景中,传统库存扣减方式弊端尽显。超卖问题因缺乏有效并发控制机制频发,多个订单同时访问库存数据,导致同一商品多次售出,订单无法履约引发客户投诉;同时&#xf…

MVCWebAPI使用FromBody接受对象的方法

近期在做软件升级操作的时候突然想着需要的参数比较多&#xff0c;如果需要参数的话参数比较多&#xff0c;所有想着使用frombody来集合数据统一操作做了个样张希望对您有帮助 代码如下&#xff1a; /// <summary>/// 入口当前文件接口下的操作数据/// </summary>/…

Atlas 800I A2 离线部署 DeepSeek-R1-Distill-Llama-70B

一、环境信息 1.1、硬件信息 Atlas 800I A2 1.2、环境信息 注意&#xff1a;这里驱动固件最好用商业版&#xff0c;我这里用的社区版有点小问题 操作系统&#xff1a;openEuler 22.03 LTS NPU驱动&#xff1a;Ascend-hdk-910b-npu-driver_24.1.rc3_linux-aarch64.run NPU固…

NLP预处理:如何 处理表情符号

一、说明 本系列文总结了在NLP处理中&#xff0c;进行文本预处理的一些内容、步骤、处理工具包应用。本篇专门谈论网上文章表情符号处理&#xff0c;对于初学者具有深刻学习和实验指导意义。 二、介绍 表情符号已成为现代交流不可或缺的一部分&#xff0c;尤其是在社交媒体、…

C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 14)

&#x1f381;个人主页&#xff1a;工藤新一 &#x1f50d;系列专栏&#xff1a;C面向对象&#xff08;类和对象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;终会照亮我前方的路 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 文章目录 二…

解锁空间数据新质生产力暨:AI(DeepSeek、ChatGPT)、Python、ArcGIS Pro多技术融合下的空间数据分析、建模与科研绘图及论文写作

人工智能&#xff08;AI&#xff09;与ArcGIS Pro的结合&#xff0c;为空间数据处理和分析开辟了前所未有的创新路径。AI通过强大的数据挖掘、深度学习及自动化能力&#xff0c;可高效处理海量、多源、异构的空间数据&#xff0c;极大提升了分析效率与决策支持能力。而ArcGIS P…

18.2.go语言redis中使用lua脚本

在 Redis 中使用 Lua 脚本可以实现原子性操作、减少网络开销以及提高执行效率。 Redis 执行 Lua 脚本的原理 Redis 内置了 Lua 解释器&#xff0c;能够直接在服务器端执行 Lua 脚本。当执行 Lua 脚本时&#xff0c;Redis 会将脚本作为一个整体执行&#xff0c;保证脚本执行期…