目录
引言
在线游戏中角色动作流畅、直播无延迟——这一切离不开一个看似“不靠谱”的协议:UDP。为什么像视频通话、实时对战游戏这样高要求的场景,反而选择不保证可靠性的UDP呢?且听我细细道来。
网络基础
两个计算机中的进程要互相通信,不仅需要知道对方的IP地址(为了找到对方的计算机),而且还要知道对方的端口号(为了找到对方计算机中的对应进程)。所以,在讲UDP协议之前,有个必不可少的知识就是要知道——IP和端口号。
IP,就是用来标识网络中不同主机的地址。端口号,就是用来标识同一台主机中的不同进程。下面我举个例子:我们在给某人写信时,必须在信封上写明Ta的通信地址(这是为了找到Ta的住所,相当于IP地址),并且还要协商收件人的姓名(因为住所里可能不止Ta一个人,这相当于端口号),明白了这一点就够了,下面我们正式进入UDP。
UDP是什么
UDP(用户数据报协议,User Datagram Protocol),存在于传输层。
UDP核心特性
1)无连接
在发送数据之前需要建立连接,当然,在发送数据结束时也没有连接可释放,因此就减少了开销和发送前的时延。
2)不可靠
尽最大努力交付。UDP没有确认机制,没有丢包后的重传机制,也不能确保数据报的按序到达(先发送的数据报后到达)。
3)面向数据报
上图是网络传输的层状结构。发送方的UDP对应用层交下来的报文,在添加完UDP报头后,就向下交付到网络层了。也就是说,UDP对应用层交下来的报文,既不合并,也不拆分,应用层给多少就向下交付多少。如果应用层交付的数据很大导致报文太长,UDP也不管,照样向下面的网络层交付,由于报文太长,发送时网络层可能要对报文进行分片,这就降低了网络层的效率。
由于UDP面向数据报的这一特点,导致它不能够灵活的读写数据。用UDP发送100字节的数据,如果发送端调用一次 sendto, 发送 100 个字节, 那么接收端也必须调用对应的 一次 recvfrom, 接收 100 个字节; 而不能循环调用 10 次 recvfrom, 每次接收 10 个字 节。
4)轻量高效
报头仅8个字节,比TCP报头的20字节少,同时又因为它无连接,所以传输延迟极低。
以上的几个特性,共同促成了UDP的——简单高效,但不可靠。
UDP报头
UDP的报头很简单,只有8个字节,由4个字段组成,每个字段长度都是2字节。
● 源端口:对方回信时需要知道源端口号。
● 目的端口:发送方在交付报文时需要知道目的端口号,才知道报文交个目的主机的哪个进程。
● 长度:UDP数据报的长度,包含报头,最小值是8(仅有报头)。
● 检验和:检测UDP数据报在传输中是否有错,有错就丢弃。
UDP用武之地
实时音视频传输:容忍少量丢包,但拒绝卡顿。
在线游戏:低延迟优先。
DNS查询:域名解析,快速简单。
如何让UDP变可靠
UDP的不可靠主要体现在:不保证数据包到达顺序、完整性(可能丢包)、不提供拥塞控制和重传机制。所以,让UDP变可靠的思路就是保证包的到达顺序以及完整性,然后在应用层提供拥塞控制和重传机制。
1)应用层添加确认应答机制(ACK):接收方收到数据包后,发送ACK报文告知发送方。
2)数据包编号:为每个数据包分配唯一序列号,用于检测丢包和乱序。
3)超时重传:发送方维护发送缓冲区,发送方在超时未收到接收方的确认应答时,重新发送未确认的数据包。
4)拥塞控制:动态调整发送速率,例如模仿TCP的AIMD算法,防止网络过载。
5)前向纠错(FEC):发送原始数据包外,额外发送校验包,接收方接收到数据包和校验包后,可以恢复部分丢包。
结语
不管是可靠还是不可靠,我更喜欢理解为TCP/UDP的一种特性,而不是优缺点,它只是采用了另一种设计哲学:用可控的“不完美”,换极致的效率——不用连接,直接起飞。
本篇博客到这里就结束啦,欢迎大家批评指正,感谢支持!