参考文档:
RFC768: User Datagram Protocol.
介绍
UDP 是User Datagram Protocol 的简称,中文名是用户数据报协议。
是OSI (Open System Interconnection,开放式系统互联)参考模型中一种无连接 的传输层协议,提供面向事务的简单不可靠信息传送服务,UDP在IP报文的协议号是17。
与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。
根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。
RFC768定义的UDP只是做了运输协议能够做的最少工作,除了复用/解复用 及少量的差错检测外,它几乎没有对IP(网络层面)增加别的东西。
2. 潜在问题
如果每个人都启动流式高比特视频而不使用任何拥塞控制的话,就会使路由器中有大量的分组溢出,以至于非常少的UDP分组能成功地通过源到目的的路径传输。
况且,由无控制的UDP发送方引入的高丢包率将引起TCP发送方(如我们看到的那样,TCP遇到拥塞将减少它们的发送速率)大大地减小它们的速率。
因此,UDP中缺乏拥塞控制能够导致UDP发送方和接收方之间的高丢包率,并挤垮了TCP会话,这是一个潜在的严重问题。很多研究人员已提出了一些新机制,以促使所有的数据源(包括UDP源)执行自适应的拥塞控制。[Mahdavi 1997, Floyd 2000, Kohler 2006, RFC 4340]
特点
-
无连接:时间上,没有建立连接带来的时延;空间上,不维护连接状态,开销小。空间和时间上都具有优势;
-
头部开销小:TCP 头部 20字节,UDP 头部仅 8字节,常用于一次性传输比较少量数据的网络应用,如 DNS、SNMP等;
-
无拥塞控制:应用层可以自己掌控发送的数据和发送的时间,某些实时应用要求以稳定的速度发送,能容忍一些数据的丢失,但是不能允许有较大的时延,比如视频通话、直播等;
-
尽最大努力交付,不保证可靠交付:所有维护传输可靠性的工作都需要应用层自己来完成。没有 TCP 的确认机制、重传机制。如果因为网络原因没有传送到对端,UDP 也不会给应用层返回错误信息;
-
面向报文 :对应用层交下来的报文,添加首部后直接向下交付给 IP 层,既不合并,也不拆分 ,保留这些报文的边界,应用层交给 UDP 多长的报文,UDP 就照样发送,即一次发送一个报文。对 IP 层交上来 UDP 包,去除首部后就原封不动地交付给应用层。报文不可分割,是 UDP 处理的最小单位。正因如此,UDP 显得不够灵活,不能控制读写数据的次数和数量。比如我们要发送100个字节的报文,我们调用一次 sendto 函数就会发送 100字节,对端也需要用 recvfrom 函数一次性接收 100字节,不能使用循环每次获取 10个字节,获取 10次这样的做法;
-
支持一对一、一对多、多对一和多对多的交互通信。
报文段结构
sql
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| Source | Destination |
| Port | Port |
+--------+--------+--------+--------+
| | |
| Length | Checksum |
+--------+--------+--------+--------+
|
| data octets ...
+---------------- ...
User Datagram Header Format [RFC768]
- 源端口号(16位):发送端口;
- 目的端口号(16位):接收端口;
- 包长度 (16位):UDP 头长度 + 数据长度;
- 通过 IPv4 协议传输时,由于IPv4的头部信息要占用20字节,因此数据长度不可能超过65507字节(65,535 − 8字节 UDP 头 − 20字节 IP 头)。
- 在 IPv6 的 jumbogram 中,是有可能传输超过 65535 字节的 UDP 数据包的。依据 RFC2675,如果这种情况发生,报文长度应被填写为 0。
- 校验和(16位):对整个 UDP 包,包括 UDP 头部和 UDP 数据的校验,该字段在 IPv4 中是可选的,在 IPv6中 则是强制的。如果不使用校验和,该字段应被填充为全0。
检验和
UDP计算校验和的方法和IP数据报首部校验和的方法相似。
不同的是:IP数据报校验和只校验IP数据报的首部,但UDP的校验和是把首部和数据部分一起都检验。
计算方式:
UDP的校验和需要计算UDP首部加数据荷载部分 ,但也需要加上UDP伪首部。
这个伪首部指,源地址、目的地址、UDP数据长度、协议类型(0x11 = 17)16进制,协议类型就一个字节,但需要补一个字节的0x0,构成12个字节。伪首部+UDP首部+数据一起计算校验和。
UDP伪首部,12字节,伪首部并不是UDP数据报的真正首部,只是为了计算检验和临时添加在UDP数据报的前面,它既不向下传送也不向上递交,它的仅仅是为了计算检验和而存在的。
IPv4 在计算检验和时,临时把「伪头部」和 UDP 用户数据报连接在一起。
计算方法:
- 按每16位求和得出一个32位的数;
- 如果这个32位的数,高16位不为0,则高16位加低16位再得到一个32位的数;
- 重复第2步直到高16位为0,将低16位取反,得到校验和。
需要注意的是,UDP校验和是一个简单的错误检测机制,它并不提供真正的安全性或数据完整性保护 。如果数据包在传输过程中发生了错误,接收方可以通过校验和检测到,但校验和无法纠正错误 ,只能通知上层应用层数据可能已经损坏。
应用
1. QUIC
QUIC 是 Google 提出的一种基于 UDP 改进的通信协议,其目的是降低网络通信的延迟,提供更好的用户互动体验。QUIC 在应用层上,已经实现了快速连接建立、减少重传时延,自适应拥塞控制。
2. 流媒体
现在直播比较火,直播协议多使用 RTMP,是基于 TCP 的,当网络不好的时候,TCP 协议会主动降低发送速度,这对本来当时就卡的看视频来讲是要命的,应该应用层马上重传,而不是主动让步。因而,很多直播应用,都基于 UDP 实现了自己的视频传输协议。
3. 实时游戏
射击、MOBA等竞技类游戏,对时延比较苛刻,卡个几百毫秒,技能放不出来就被别人打死了,对实时要求较为严格的情况下,采用自定义的可靠 UDP 协议,自定义重传策略,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性造成的影响。
4. IOT物联网
一方面,物联网领域终端资源少,很可能只是个内存非常小的嵌入式系统,而维护 TCP 协议代价太大。
另一方面,物联网对实时性要求也很高,而 TCP 还是因为上面的那些原因导致时延大。Google 旗下的 Nest 建立 Thread Group,推出了 物联网通信协议 Thread,就是基于 UDP 协议的。