目录

网络-06 UDP 与 TCP 对比

前置阅读:网络-03 IP 协议 传输层从这一篇开始。先讲简单的 UDP,再用它作为参照理解 TCP 为什么复杂——TCP 详见 网络-07 起的三篇。

1. UDP 首部格式

./udp首部格式.png 这个伪首部是模仿的IP数据报的首部,只有在计算校验和时才出现,不向下传递也不向上递交。

udp数据包的理论长度是多少,合适的udp数据包应该是多少呢? 从udp数据包的包头可以看出,udp的最大包长度是2^16-1的个字节。由于udp包头占8个字节,而在ip层进行封装后的ip包头占去20字节,所以这个是udp数据包的最大理论长度是2^16-1-8-20=65507。

然而这个只是udp数据包的最大理论长度。UDP属于运输层,在传输过程中,udp包的整体是作为下层协议的数据字段进行传输的,它的长度大小受到下层ip层和数据链路层协议的制约。

udp是不会对应用层的数据报进行合并或拆分的。

2. UDP 的特点

  1. 面向无连接 首先 UDP 是不需要和 TCP一样在发送数据前进行三次握手建立连接的,想发数据就可以开始发送了。并且也只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操作。
  2. UDP是面向报文的 发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。因此,应用程序必须选择合适大小的报文
  3. 不可靠性 首先不可靠性体现在无连接上,通信都不需要建立连接,想发就发,这样的情况肯定不可靠。 并且收到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。 再者网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是 TCP。
  4. 头部开销小,传输数据报文时是很高效的。 因此 UDP 的头部开销小,只有八字节,相比 TCP 的至少二十字节要少得多,在传输数据报文时是很高效的

3. TCP 和 UDP 的比较

  1. 对比
对比项 UDP TCP
是否连接 无连接 面向连接
是否可靠 不可靠传输,不使用流量控制和拥塞控制 可靠传输,使用流量控制和拥塞控制
连接对象个数 支持一对一,一对多,多对一和多对多交互通信 只能是一对一通信
传输方式 面向报文 面向字节流
首部开销 首部开销小,仅8字节 首部最小20字节,最大60字节
适用场景 适用于实时应用(IP电话、视频会议、直播等) 适用于要求可靠传输的应用,例如文件传输

4. 选型总结

TCP向上层提供面向连接的可靠服务 ,UDP向上层提供无连接不可靠服务。 虽然 UDP 并没有 TCP 传输来的准确,但是也能在很多实时性要求高的地方有所作为 对数据准确性要求高,速度可以相对较慢的,可以选用TCP

5. UDP 之上的可靠传输

UDP 不可靠,但这不代表"用 UDP 就只能不可靠"。恰恰相反,在 UDP 之上自己实现可靠传输是近年最重要的网络趋势:

  • QUIC:Google 主导、现已成为 IETF 标准(RFC 9000),在 UDP 之上重建了一整套可靠传输 + 拥塞控制 + 加密,HTTP/3 就跑在它上面。它是目前最重要的例子,详见 网络-18 HTTP/3 与 QUIC
  • KCP:国内游戏和实时通信领域常用,以牺牲带宽(约 10%~20% 冗余)换取比 TCP 低 30%~40% 的延迟。
  • WebRTC 的数据通道:基于 UDP + SCTP,实时音视频的事实标准。

为什么要绕开 TCP 自己重做一遍? 三个理由:

  1. TCP 的队头阻塞无法绕过——它必须按序交付,一个包丢了后面全等着(详见 网络-18);
  2. TCP 在内核里,迭代太慢——改一个算法要等操作系统普及,周期以年计;而 UDP 之上的协议跑在用户态,发个版就能升级;
  3. 中间设备只认 TCP 和 UDP——想部署一个全新的传输层协议(如 SCTP)基本不可能,防火墙和 NAT 会直接丢弃。

所以现代的做法是:把 UDP 当成一个"能穿过网络的信封",可靠性、拥塞控制、加密全在用户态自己实现。这也解释了为什么 UDP 虽然功能极简,却反而成了新协议的地基——它的简单正是它的价值

6. 那 DNS、DHCP 为什么用 UDP

除了实时音视频,另一类经典的 UDP 场景是短小的请求-响应

  • DNS(见 网络-11):一次查询一个包、一次响应一个包,用 TCP 光握手就要 1 个 RTT,纯属浪费。丢了直接重查即可。注意 DNS 响应超过 512 字节时会切换到 TCP。
  • DHCP:客户端此时还没有 IP 地址,根本没法建立 TCP 连接,只能靠 UDP 广播。
  • SNMP、NTP、syslog:都是"发出去就好,丢一两个无所谓"的场景。

判断标准很朴素:如果重传的代价比丢弃更高,就用 UDP。 实时语音里一个迟到 500ms 的包已经没有意义了,重传它反而不如直接丢掉播下一帧。

7. 本章面试题

TCP 和 UDP 的区别?各适合什么场景?
UDP TCP
连接 无连接 面向连接
可靠性 不可靠,无流控无拥塞控制 可靠,有流控和拥塞控制
传输方式 面向报文(保留边界) 面向字节流(不保留边界)
首部开销 8 字节 20~60 字节
通信对象 支持一对多、多对多 只能一对一

选型标准很朴素:如果重传的代价比丢弃更高,就用 UDP。 实时语音里一个迟到 500ms 的包已经没意义了,重传它不如直接丢掉播下一帧。

UDP 场景:实时音视频、直播、游戏,以及短小的请求-响应(DNS、DHCP、NTP、SNMP)。 TCP 场景:文件传输、网页、任何要求数据完整的场合。

为什么 UDP 不会粘包,TCP 会?

因为传输方式不同

  • UDP 面向报文——保留应用层的消息边界,既不合并也不拆分,一次 sendto 对应一次 recvfrom。所以应用程序必须自己选择合适的报文大小。
  • TCP 面向字节流——它眼里只有连续的字节,从设计上就不承诺保留消息边界,多次 write() 的数据可能被合并(Nagle 算法、缓冲区),一次 write() 的数据也可能被拆开(超过 MSS)。

所以 TCP 需要应用层自己定义消息边界(长度前缀、分隔符、定长),详见 网络-08

DNS 为什么用 UDP?什么时候会用 TCP?

用 UDP 的原因:一次查询一个包、一次响应一个包,用 TCP 光握手就要多 1 个 RTT,纯属浪费。丢了直接重查即可。

改用 TCP 的两种情况

  1. 响应超过 512 字节——响应里置 TC(Truncated)标志位,客户端改用 TCP 重发查询;
  2. 主从区域传输(AXFR/IXFR)——数据量大且要求可靠。

所以防火墙只放开 UDP 53 是错的,典型故障是"小域名正常、返回记录多的大域名稳定失败"。详见 网络-11

UDP 不可靠,为什么 QUIC 还要基于 UDP?

因为换传输层比改 TCP 容易。三个理由:

  1. TCP 的队头阻塞无法绕过——它必须按序交付,一个包丢了后面全等着;
  2. TCP 在内核里,迭代太慢——改一个算法要等操作系统普及,周期以年计;而 UDP 之上的协议跑在用户态,发版就能升级;
  3. 中间设备只认 TCP 和 UDP——想部署全新的传输层协议(如 SCTP)基本不可能,防火墙和 NAT 会直接丢弃。

所以现代做法是把 UDP 当成"能穿过网络的信封",可靠性、拥塞控制、加密全在用户态自己实现。UDP 的简单正是它的价值。

同类例子:KCP(游戏)、WebRTC 数据通道。详见 网络-18