UDP是一种无连接的、简单的传输层协议,UDP协议的设计目的是提供一种简单、轻量级的通信机制,适用于那些对实时性和传输效率有较高要求,但对数据完整性和可靠性要求相对较低的应用。
UDP协议报头
UDP协议的报头部分由四部分组成:源端口号,目的端口号,UDP长度,校验和。
- 源端口号:识别发送方的端口号。
- 目的端口号:识别接收方的端口号。
- 长度:指定UDP数据报的长度,包括UDP头部和UDP数据的总长度。
- 校验和:检测头部、数据以及可能的填充字节在传输过程中的错误。
在这里可能会有读者有疑问为什么只有源端口号与目的端口号,没有源IP地址与目的IP地址(IP地址负责在网络中标识唯一主机,而端口号负责在主机上标识进程),UDP协议是传输层协议,UDP协议运行在IP协议上,IP协议负责在不同网络设备之间传输数据包。所以IP地址是在网络层即IP协议所在层添加的。
校验和
校验和用来检测数据在传输过程中是否发生错误。
校验和的计算
UDP/TCP协议会准备一个伪头部,它并不实际包含在数据包中,而是为了计算校验和而构造的一组虚拟的头部信息。伪头部的结构如下:
- 源IP地址:发送方的IP地址,4字节。
- 目的IP地址:接收方的IP地址,4字节。
- 保留字段:通常设置为0,8字节(64位)。
- 协议:指出上层协议的类型,1字节。对于UDP,这个值是17。对于TCP,这个值是6。
- UDP或TCP长度:UDP或TCP数据包的长度,包括UDP或TCP头部和数据,2字节。
之后会将伪头部、UDP/TCP头部(校验和字段被设置为0)和数据载荷连续拼接成一个数据块。
整个数据块的长度需要是16位(2字节)的整数倍。如果不是,需要后面添加零,直到满足条件。
接下来就是校验和的计算:
- 将数据块分成16位的分组。
- 对每个16位分组进行二进制加法。
- 如果加法结果超过16位,将进位加到下一个分组的最低位。
- 对所有分组进行此操作。
计算出最终结果后会对结果进行按位取反,然后填充到报头校验和字段。
校验和的检查
接收方获取了数据报后,会重新按照上面的方法计算校验和。如果两者相等,则证明数据完整,否则,说明数据在传输过程中损坏,会将报文直接丢弃。
注意:UDP的校验和是可选的,如果发送方没有计算校验和,字段会被设置为0。接收方在处理UDP数据包时,如果发现校验和字段为0,会忽略校验和的检查。
面向数据报
UDP是一种面向数据报的协议,它按照独立的数据块(即数据报)发送和接收信息。
简而言之,应用层交给UDP多长的报文, UDP原样发送, 既不会拆分, 也不会合并。用UDP传输100个字节的数据:
如果发送端调用一次sendto,发送100个字节, 那么接收端也必须调用对应的一次recvfrom,接收100个字节。 而不能循环调用10次recvfrom, 每次接收10个字节。
基于面向数据报的特点使UDP有以下特性:
- UDP不建立持久的连接。发送方和接收方之间的通信不需要预先建立连接,每个数据报的发送和接收都是独立于其他数据报的。
- UDP协议也不保证数据报的顺序。如果多个数据报同时发送,它们可能因为网络条件的差异而以不同的顺序到达目的地。
- UDP不保证数据报的传输。数据报可能会在传输过程中丢失、重复或损坏,UDP协议本身不提供重传机制。
UDP的面向数据报的特性使其非常适合那些需要快速、简单传输的场景,如网络直播,实时游戏等。
缓冲区
发送缓冲区
UDP实际上没有真正意义上的发送缓冲区,在发送数据时会直接交付内核完成发送,这是因为UDP的特性,不需要保证可靠性,因此不需要重传,也就不需要使用发送缓冲区暂存数据。
在我们介绍TCP协议时会详细介绍TCP的发送缓冲区,以及其如何保证可靠性。
接收缓冲区
每个UDP套接字都存在一个接收缓冲区,在接收到UDP报文后会暂存在接收缓冲区,等待上层读取。在缓冲区满的情况下,接收到的报文会被直接丢弃。
UDP优缺点
优点:
简单性:UDP的协议栈比TCP简单,因为它不需要建立连接、维护状态或重传丢失的数据包。
低延迟:由于UDP不需要建立连接和确认数据包,它可以提供较低的延迟。
资源消耗少:UDP不需要维护连接状态,因此它消耗的资源比TCP少。
无需拥塞控制:UDP不进行拥塞控制,不会因为网络拥塞而降低发送速率。
适用性:UDP适用于那些对数据传输速度要求高但可以容忍一定数据丢失的应用,如流媒体和实时通信。
缺点:
不可靠性:UDP不保证数据包的送达,可能会发生数据丢失、重复或乱序到达。
缺乏流量控制:UDP不提供流量控制机制,会导致接收方因为数据包到达速度过快而无法处理。
无拥塞控制:由于UDP不进行拥塞控制,它可能会在网络拥塞时加剧网络拥塞。
不适合大文件传输:对于需要可靠传输的大文件,UDP不是最佳选择,因为其不保证数据的完整性和顺序。
需要应用层处理:由于UDP提供的是无连接服务,所有与连接相关的处理(如重传、排序)都需要在应用层实现。