五个维度看清差异
| 维度 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接(握手 + 状态) | 无连接,每个数据报独立 |
| 可靠性 | 确认、重传、按序交付 | 不保证送达,也不保证顺序 |
| 拥塞控制 | 内建,会主动降速 | 没有,需要自己在应用层实现 |
| 头部开销 | 20 字节以上(含选项更多) | 8 字节 |
| 延迟表现 | 丢包时等待重传,延迟抖动大 | 不等重传,抖动小但可能丢数据 |
什么时候选 UDP
- 实时音视频:晚到的数据包没有意义,宁可丢也不等;
- 在线游戏:状态频繁更新,最新一帧比补旧帧重要;
- 短查询:如 DNS,一次往返完事,重传由应用层控制更简单;
- 自定义传输:QUIC 就是在 UDP 之上重建了一套更现代的传输机制。
什么时候必须用 TCP
- 文件、数据库、消息:任何「一个字节都不能少」的场景;
- 需要严格顺序:如日志流、复制通道;
- 不想自己造轮子:重传、拥塞控制与粘包处理都很复杂,能用现成的就别自己写。
在 UDP 上要自己补的四件事
- 序号:用于检测丢失与乱序;
- 重传策略:什么时候重传、重传几次后放弃;
- 拥塞控制:否则会在弱网下把链路打满,影响所有业务;
- 分片与 MTU:超过 MTU 会在 IP 层分片,丢一片即整包作废,应在应用层控制报文大小。
常见误区
- 「UDP 会丢包所以不能用」:错。关键是业务能否容忍丢包,以及你是否在应用层做了补偿;
- 「UDP 一定更快」:不一定。省下的是握手与队头阻塞,但若你在应用层重做了重传,往往还不如直接用 TCP;
- 「TCP 不会丢」:TCP 只是负责把丢的包补回来,应用层仍可能超时,且超时时长由重传决定。
一个常被忽略的细节:消息边界
TCP 是字节流,没有消息边界:多次 send 的数据可能被合并或拆分,应用层必须用长度前缀、分隔符或固定结构自行组帧。UDP 保留数据报边界——一次发送对应一次接收,但这也要求每个报文自成一体,不能依赖前后报文拼装。
与 HTTP/3 的关系
HTTP/3 基于 QUIC,而 QUIC 建立在 UDP 之上。它这样做的目的不是「不要可靠性」,而是把重传、拥塞控制与 TLS 放进同一层,既保留可靠传输,又避免了 TCP 的队头阻塞——一个包丢失时不会卡住所有流。
常见问题
做内网 RPC 用哪个?除非你有成熟的传输层经验,否则用 TCP(或 HTTP/2、gRPC)。实时对战游戏用 TCP 会怎样?丢包后的重传等待会让操作明显发涩,这正是它们选择 UDP 的原因。如何测试 UDP 质量?关注丢包率、抖动与乱序率三项,而不只是带宽。
哪些应用层协议跑在 UDP 上
- DNS:默认 UDP 53,响应过大或需要可靠传输时回退 TCP 53,这也是“某些域名查询特别慢”的原因之一;
- QUIC / HTTP3:基于 UDP 自行实现可靠性与拥塞控制,必须放行 UDP 443;
- 实时音视频:RTP 走 UDP,宁可丢帧也不重传,重传带来的延迟比丢包更难忍受;
- VPN 与隧道:WireGuard 用 UDP,需注意部分网络会限速或封禁 UDP。
迁移到 QUIC 的注意点
- 确认中间设备放行 UDP 443,并对被拦截的客户端保留 HTTP/2 回退;
- HTTP/3 的连接迁移依赖连接 ID,NAT 超时较短时需相应调整保活;
- 监控回退比例与握手失败率,这两项最能反映实际可用性。
选型时的三个问题
一是“丢一个包要不要重发”?必须重发就用 TCP;二是“能不能接受建立连接的开销”?短连接小请求密集时,连接复用比协议选择影响更大;三是“中间设备会不会拦”?UDP 在部分企业网络中受限,设计时就要准备 TCP 回退路径。