【Linux篇章】再续传输层协议UDP :从低可靠到极速传输的协议重生之路,揭秘无连接通信的二次进化密码!

【Linux篇章】再续传输层协议UDP :从低可靠到极速传输的协议重生之路,揭秘无连接通信的二次进化密码!

📌本篇摘要:

  • 本篇将承接上次的UDP系列网络编程,来深入认识下UDP协议结构,特性,底层原理,注意事项及应用场景
在这里插入图片描述


在这里插入图片描述
🏠欢迎拜访🏠:点击进入博主主页
📌本篇主题📌:再续UDP协议
📅制作日期📅:2025.09.01
🧭隶属专栏🧭:
点击进入所属Linux专栏

一.🔍再识UDP协议

  • 传输层:负责数据能够从发送端传输到接收端。
  • 可以先理解成用于数据在传输层封装的协议。

💡再认识传输层上面那常见的几个层结构:

会话层:用于连接与断开的(如tcp)。

表示层:可以理解成之前我们用于序列化与反序列化。

应用层:用户设计一些通信完成的功能。

这里UDP就是在这层工作的:

在这里插入图片描述

二.🔥重新认识下端口号

  • TCP/IP协议(包含UDP)中常见五元组:“源 IP”, “源端口号”, “目的 IP”, “目的端口号”, “协议号”(可以用netstat -n 查看)。

端口号范围划分

  • 0 - 1023:知名端口号, HTTP, FTP, SSH 等这些广为使用的应用层协议, 他们的端口号都是固定的。
  • 1024 - 65535:操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的。</font>

认识知名端口号(Well-Know Port Number)

有些服务器是非常常用的,为了使用方便,人们约定一些常用的服务器,都是用以下这些固定的端口号:

  • ssh 服务器,使用 22 端口。
  • ftp 服务器,使用 21 端口。
  • telnet 服务器,使用 23 端口。
  • http 服务器,使用 80 端口。
  • https 服务器,使用 443端口。

使用下面指令查看知名端口号(也就是我们网络通信的时候绑定要避开的端口号):

cat /etc/services 

如下:

在这里插入图片描述

💡重新认识下之前的两个问题:

  • 一个进程是否可以 bind 多个端口号?
  • 一个端口号是否可以被多个进程 bind?

原因:端口号的目的是通过它找到指定进程!

三.⚠️ UDP 协议端格式

首先看张图了解下:

在这里插入图片描述

上面有了五大元组的目的端口号与源端口号(剩下的会在ip层完成封装)

  • 16 位 UDP 长度表示整个数据报(UDP 首部+UDP 数据)的最大长度。
  • 16位UDP校验和:如果校验和出错,就会直接丢弃。

⚠️那么数据如果要是有的话,可以是2^16-1-8个字节数据, 如果比它多了就需要应用层手动的分包,多次发送,并在接收端手动拼装

其实传输的就是上面样式的结构体:

structudphdr{uint16_t uh_sport;/* 源端口 */uint16_t uh_dport;/*目的端口 */uint16_t uh_ulen;/* UDP 长度 */ uint16 _t uh_sum;/*校验和 */};

因为内核规定的端口号就是16位,因此我们要传递的就是这个格式。

四. ⏳UDP特点

  • 无连接:知道对端的 IP 和端口号就直接进行传输,不需要建立连接。
  • 不可靠:没有确认机制,没有重传机制;如果因为网络故障该段无法发到对方,UDP 协议层也不会给应用层返回任何错误信息。
  • 面向数据报:不能够灵活的控制读写数据的次数和数量。

下面再深入了解下不可靠性以及面向数据报

1. 🎆对于它的不可靠性:

-udp无发送缓冲区(即没有传统意义上的发送缓冲区,但有内核级的待发送数据暂存区​​),故不能像tcp那样可以先把数据储存在发送缓冲区,如果它的接收缓冲区满了导致没收到数据,就可以再次把保存在发送缓冲区的数据再发一次!udp如果发送的时候接收缓冲区满了,或者其他原因就会丢包现象!

2. 🎆对于面向数据报:

  • 应用层交给 UDP 多长的报文,UDP 原样发送,既不会拆分,也不会合并:
比如UDP传输100字节数据,如果发送端调用一次 sendto,发送 100 个字节,那么接收端也必须调用对应的1次 recvfrom,接收 100 个字节; 而不能循环调用 10 次recvfrom,每次接收 10 个字节
  • 可以简单理解成udp对数据发的信息原样转发出去,不能像tcp那样灵活读取,这里就认为是一团数据,一口气发送或者接收!

五. UDP缓冲区

  • UDP 没有真正意义上的发送缓冲区,数据直接交内核尝试发送,内核仅极短暂暂存少量包,不保证数据会持久化在缓冲区中​​,失败则 sendto() 报错,不保证可靠传输,(其中调用 sendto 会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作)。
  • UDP 具有接收缓冲区,但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致; 如果缓冲区满了,再到达的 UDP 数据就会丢弃。

这里有个疑问,为啥它没发送缓冲区?

  • 面向用户数据报:它只要遇到用户准备的数据就直接进行转发!
  • 无连接特性:不用像tcp那样先连接好才能通信,需要等待这个时间,所以把它放到对应的发送缓冲区!
  • 3.尽力而为服务:它是不可靠的,udp只管完成认为把用户准备发的信息发送出去,不管可靠交付、顺序到达以及无重复等!
  • 4.实时性要求:一般适用于如音频、视频流的传输等需要实时更新的任务,如果设置了发送缓冲区,就会导致数据等待而产生延迟,这点就不能保证了!

六.底层基于 UDP 的应用层协议

  • NFS: 网络文件系统。
  • TFTP:简单文件传输协议。
  • DHCP:动态主机配置协议 比如路由器给电脑分配的ip地址。
  • BOOTP:启动协议(用于无盘设备启动)。
  • DNS:域名解析协议 http时候的解析域名成ip。
  • 当然,也包括自己写 UDP 程序时自定义的应用层协议。

常用于 可靠性低 允许丢包 语音 比赛等实时性高的通信任务!

七.🎃OS如何管理封装的报文

首先我们说到了UDP有接收缓冲区,当收到数据包的时候,OS也是需要管理的。

首先我们先理解一下sk _buff这里就是os用来管理在那几层传递的报文:

下面看张图(这里把TCP换成UDP是一样的):

在这里插入图片描述
  • 假设操作系统收到对应的报文,在链路层进行“先描述后组织“(可以认为就是对sk_buff进行链表式的组织然后就能通过里面对应的指针找到内存里的数据!),再一层一层往上交互进行解包等操作。

这里只需要认识四个指针:

  • head,end就是对应的内存空间划分。
  • data,tail就会是对应数据,当进行发送就要添加不同层的报头,那么此时data就–,如果是进行接收也就是解包,此时data再++,tail标识的就是这段报文的结尾.

也就是根据 报文 =报头+ 有效载荷 这一原则进行的。

sk_buff结构代码如下:

structsk_buff{/* List management pointers */structsk_buff_head*list;structsk_buff*next;/* Control buffer for private use */char cb[48]__aligned(8);/* Pointers to the data in the buffer */unsignedchar*head,*data;unsignedchar*tail,*end;/* Length of the buffer */unsignedint truesize;/* Reference count */ atomic_t users;/* State flags */unsignedint state;/* Destructor function */void*destructor;/* Protocol type */ __be16 protocol;/* Length of the packet */unsignedint len;/* Length of the data in the buffer */unsignedint data_len;/* MAC header length */ __u16 mac_len;/* Network header length */ __u16 network_header_len;/* Transport header length */ __u16 transport_header_len;/* Timestamp */structtimespec64 tstamp;/* Socket pointer */structsock*sk;/* Network device pointer */structnet_device*dev;/* Space in front of data (headroom) */unsignedint headroom;/* Space at the end of data (tailroom) */unsignedint tailroom;};

这里只需大致了解一下即可!

❗此时还有个小问题:

如果应用层正在进行报文的解析,处理,会不会影响OS继续从网络中读取报文?

  • 答:不会,因此我们就可以知道,当udp在进行数据接收后在进行解析的时候(应用层),但是底层还是会不断接收信息(以sk_buff形式管理),也就是利用了os的中断机制了,因此是可以同时进行的!

八.📌UDP协议总结

🔍特性分析

  • 核心特性:无连接、不可靠传输,以数据报为单位,首部仅8字节,传输效率高。
  • 优势:无需建立连接,传输速度快、延迟低,支持广播/多播 ,资源消耗少。
  • 劣势:不保障数据完整性、有序性,易丢包,网络差时问题更突出。

🔍应用场景及注意事项:

  • 实时音视频(直播、视频会议、语音通话)

应用原因:低延迟保证画面、声音连贯性。

注意事项:需在应用层补充丢包恢复机制(如FEC前向纠错)、抗抖动缓冲处理。

  • 在线游戏

应用原因:快速传输玩家操作信息,确保游戏流畅。

注意事项:增加状态同步机制,解决少量数据丢失或乱序问题。

  • 网络管理(SNMP)

应用原因:频繁发送管理信息,UDP开销小更合适。

注意事项:关键管理指令需设计应用层确认重传机制。

  • 广播与多播(网络电视、在线广播)

应用原因:支持同时向多目标发送相同数据。

注意事项:对带宽依赖高,需控制数据报大小,避免网络拥塞 。

九.📌本篇小结

  • 本篇介绍了在之前经历了UDP编程后,有了一定基础认识,再深入的了解了UDP大致结构及相关信息后,更加丰富了对UDP的理解,后续将进行TCP相关的讲解,欢迎订阅!

Read more

C++ 继承入门(下):友元、静态成员与菱形继承的底层逻辑

C++ 继承入门(下):友元、静态成员与菱形继承的底层逻辑

🔥小叶-duck:个人主页 ❄️个人专栏:《Data-Structure-Learning》 《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--从优选到贪心 ✨未择之路,不须回头 已择之路,纵是荆棘遍野,亦作花海遨游 目录 前言 一. 友元 —— 友元关系不可继承   1、错误版本   2、正确版本 二. 静态成员 —— 继承体系中静态成员的共享性 三. 多继承及菱形继承问题:本质特点与解决方案   1、单继承与多继承模型   2、菱形继承:虚继承解决“数据冗余”与“二义性”     2.1 菱形继承出现的坑(解决二义性问题)     2.2 虚继承:彻底解决菱形继承问题     3、多继承中指针偏移问题 友元,静态成员,

By Ne0inhk
《C++进阶之STL》【哈希表】

《C++进阶之STL》【哈希表】

【哈希表】目录 * 前言 * ------------概念介绍------------ * 1. 什么是哈希? * ------------核心术语------------ * 一、哈希函数 * 1. 哈希函数的核心特点是什么? * 2. 哈希函数的设计目标是什么? * 3. 常见的哈希函数有哪些? * 直接定址法 * 除法散列法 * 乘法散列法 * 全域散列法 * 二、负载因子 * 1. 什么是负载因子? * 2. 负载因子对哈希表的性能有什么影响? * 3. 负载因子超过阈值时会发什么? * 三、哈希冲突 * 四、冲突处理 * 方法一:开放定址法 * 线性探测 * 二次探测 * 双重散列 * 方法二:链地址法 * ------------基本操作------------ * 怎么解决键key不能取模的问题? * 一、开放定址法 * 哈希结构 * 删除操作 * 扩容操作 * 二、链地址法 * 哈希结构 *

By Ne0inhk

5步彻底解决Visual C++运行库安装失败问题

5步彻底解决Visual C++运行库安装失败问题 【免费下载链接】vcredistAIO Repack for latest Microsoft Visual C++ Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否遇到过Visual C++ Redistributable安装时突然闪退,或者进度条卡住不动的情况?这些问题往往源于系统环境复杂性和版本兼容性冲突。VisualCppRedist AIO项目通过智能化的全合一解决方案,帮助用户高效处理这些棘手的安装问题。 快速诊断:找出安装失败的根本原因 识别常见的安装失败症状 在解决问题之前,首先要准确识别问题类型。Visual C++运行库安装失败通常表现为以下几种典型症状: * 静默闪退:双击安装程序后没有任何提示直接消失 * 进度条卡死:安装过程卡在某个特定百分比无法继续 * 错误代码提示:出现0x80070666(产品已安装)或其他特定错误代码 * 权限不足警告:提示需要管理员权限但即使以管理员身份运行

By Ne0inhk
C++波澜壮阔40年|类和对象篇:拷贝构造与赋值重载的演进与实现

C++波澜壮阔40年|类和对象篇:拷贝构造与赋值重载的演进与实现

🔥@雾忱星: 个人主页 👀专栏:《数据结构与算法入门指南》、《C++学习之旅》 💪学习阶段:C/C++、数据结构与算法 ⏳“人理解迭代,神理解递归。” 文章目录 * 引言 * 一、拷贝构造函数 * 1.1 解析:拷贝构造特点 * 1.2 关键:拷贝构造的调用 * 二、赋值运算符重载 * 2.1 铺垫:运算符重载特点 * 2.1.1 核心:理解运算符重载 * 2.2 进阶:赋值运算符重载特点 * 2.2 核心:理解赋值运算符重载 * 总结 引言 在C++面向对象编程中,对象的复制操作无处不在。无论是函数传参、返回值传递,

By Ne0inhk