网络-06 UDP 与 TCP 对比
前置阅读:网络-03 IP 协议 传输层从这一篇开始。先讲简单的 UDP,再用它作为参照理解 TCP 为什么复杂——TCP 详见 网络-07 起的三篇。
1. UDP 首部格式
这个伪首部是模仿的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 的特点
- 面向无连接 首先 UDP 是不需要和 TCP一样在发送数据前进行三次握手建立连接的,想发数据就可以开始发送了。并且也只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操作。
- UDP是面向报文的 发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。因此,应用程序必须选择合适大小的报文
- 不可靠性 首先不可靠性体现在无连接上,通信都不需要建立连接,想发就发,这样的情况肯定不可靠。 并且收到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。 再者网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是 TCP。
- 头部开销小,传输数据报文时是很高效的。 因此 UDP 的头部开销小,只有八字节,相比 TCP 的至少二十字节要少得多,在传输数据报文时是很高效的
3. TCP 和 UDP 的比较
- 对比
| 对比项 | 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 自己重做一遍? 三个理由:
- TCP 的队头阻塞无法绕过——它必须按序交付,一个包丢了后面全等着(详见 网络-18);
- TCP 在内核里,迭代太慢——改一个算法要等操作系统普及,周期以年计;而 UDP 之上的协议跑在用户态,发个版就能升级;
- 中间设备只认 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 的两种情况:
- 响应超过 512 字节——响应里置 TC(Truncated)标志位,客户端改用 TCP 重发查询;
- 主从区域传输(AXFR/IXFR)——数据量大且要求可靠。
所以防火墙只放开 UDP 53 是错的,典型故障是"小域名正常、返回记录多的大域名稳定失败"。详见 网络-11。
UDP 不可靠,为什么 QUIC 还要基于 UDP?
因为换传输层比改 TCP 容易。三个理由:
- TCP 的队头阻塞无法绕过——它必须按序交付,一个包丢了后面全等着;
- TCP 在内核里,迭代太慢——改一个算法要等操作系统普及,周期以年计;而 UDP 之上的协议跑在用户态,发版就能升级;
- 中间设备只认 TCP 和 UDP——想部署全新的传输层协议(如 SCTP)基本不可能,防火墙和 NAT 会直接丢弃。
所以现代做法是把 UDP 当成"能穿过网络的信封",可靠性、拥塞控制、加密全在用户态自己实现。UDP 的简单正是它的价值。
同类例子:KCP(游戏)、WebRTC 数据通道。详见 网络-18。
xingliuhua