跳到主要内容

TCP 与 UDP:核心区别、典型场景与前端关联

前端同学在排查“接口慢”“丢消息”“视频卡顿”“WebSocket 断开”这类问题时,常常会被问到:你知道这背后走的是 TCP 还是 UDP 吗?

这篇文档会用通俗方式把 TCP/UDP 讲清楚:它们分别解决什么问题、为什么差异这么大、各自适合什么场景,以及和前端常见技术(HTTP/3、WebSocket、WebRTC、DNS)的对应关系。

一句话理解

TCP 像“打电话”:先建立连接、按顺序、保证送达(更可靠)。
UDP 像“发短信/广播”:直接发出去、不保证到达与顺序(更轻量、更实时)。


1. 先把位置放对:它们在协议栈的哪一层?

TCP 和 UDP 都属于传输层协议(Transport Layer)。它们的上面是应用层协议(HTTP、WebSocket、DNS、WebRTC 的一部分等),下面是 IP(负责寻址与路由)。

如果你对“分层”的整体概念还不熟,建议先看:TCP/IP 体系结构(协议栈)入门


2. TCP 是什么:可靠的“字节流”传输

TCP(Transmission Control Protocol)核心目标是:在不可靠的网络上,提供可靠、按序、无重复的传输

2.1 你需要记住的 4 个关键词

  • 面向连接:通信前要先建立连接,结束时要拆连接(连接是有“状态”的)。
  • 可靠传输:通过确认应答(ACK)、超时重传、校验等机制尽量保证送达。
  • 按序到达:接收端会按序重组数据(乱序到达也能拼回去)。
  • 字节流:TCP 传的是“连续字节”,没有消息边界(这点非常关键)。
重要:TCP 没有“消息边界”

write 两次,并不意味着对方 read 会收到两次。对方可能一次读到两次的拼接,也可能一次只读到半条。
这也是很多“粘包/拆包”“SSE 消息粘连/截断”问题的根源之一。

想更深入理解 TCP 建连/断连过程,可以直接看:TCP 三次握手与四次挥手

2.2 TCP 为什么“可靠”?

从学习角度,你可以把 TCP 的可靠性理解为“几套机制的组合拳”:

  • 序列号(Sequence Number):给字节编号,方便按序重组、识别丢失。
  • 确认应答(ACK):告诉对方“我收到了哪些字节”。
  • 重传(Retransmission):没收到 ACK 就重发(超时/快速重传等)。
  • 滑动窗口(Window)+ 流量控制:别把接收方撑爆(接收方告诉发送方“我还能收多少”)。
  • 拥塞控制:网络拥堵时自动“降速”,避免把网络打爆(慢启动、拥塞避免等)。

3. UDP 是什么:轻量的“报文”传输

UDP(User Datagram Protocol)可以理解为:在 IP 之上做了端口封装的一层“尽力而为”传输

3.1 UDP 的典型特征

  • 无连接:发送方不需要先握手,想发就发(协议层面不维护连接状态)。
  • 不保证可靠性:可能丢包、重复、乱序;也不会自动重传。
  • 有消息边界:一次 send 对应一个数据报(接收时按“报文”交付,而不是字节流)。
  • 头部更小:开销更低(更“轻”)。
  • 更适合多播/广播:工程上常用于广播、组播等场景(TCP 天生是点对点)。
关键心法

UDP 不是“快”,而是“少做事”:不握手、不重传、不做排序/拥塞控制(这些要么不要,要么交给上层协议做)。

3.2 UDP 报文大小与 MTU:为什么 UDP 不适合“发大包”?

UDP 一次 send 对应一个数据报。如果数据报太大,超过链路能承载的 MTU(例如以太网常见 MTU 是 1500),就可能发生 IP 分片

分片带来的问题是:

  • 任何一个分片丢了,整条 UDP 报文就没了(接收端无法拼回完整数据报)。
  • 某些网络设备/NAT/防火墙对分片不友好,分片更容易被丢弃。

因此工程实践里,基于 UDP 的协议通常会尽量控制单个包的大小,并在上层做分片/重组(或做路径 MTU 探测)。这也是你会看到很多“实时协议喜欢小包、频繁发”的原因之一。


4. TCP vs UDP:一张表快速对比

对比项TCPUDP
是否需要连接是(面向连接)否(无连接)
可靠性高:确认/重传/按序/去重低:尽力而为,可能丢/乱序/重复
传输单位字节流(无边界)数据报(有边界)
是否按序不保证
头部开销大(最小 20 字节起)小(8 字节)
拥塞/流量控制协议内置协议不提供(需上层自律)
典型应用HTTP/1.1、HTTP/2、WebSocket、SSHDNS、音视频、实时游戏、QUIC(HTTP/3) 的承载层

注意:HTTP/3 是“跑在 UDP 上的 QUIC”,并不是“HTTP 直接用 UDP”。QUIC 在 UDP 之上自己实现了很多类似 TCP 的能力。


5. 为什么实时音视频/游戏更偏爱 UDP?

很多实时场景的目标不是“100% 不丢”,而是“尽量低延迟”。这会导致一个很直观的取舍:

  • TCP 丢包后会重传,旧数据晚到可能仍然要按序交付 → 延迟抖动会变大。
  • 音视频里“晚到的旧帧”往往没价值,宁可丢掉也要保证新帧及时到 → UDP 更适合。

但这不代表 UDP 就“什么都不管”。真实系统一般会在 UDP 之上再做一层(或多层)能力,例如:

  • 序号/时间戳:识别乱序与过期数据。
  • 抖动缓冲(jitter buffer):平滑网络抖动。
  • 丢包恢复:重传(选择性)、前向纠错(FEC)等。
  • 带宽估计与拥塞控制:避免把网络挤爆(不然你再实时也会卡死)。

前端相关例子:WebRTC 通常优先走 UDP 来承载媒体流(再叠加 DTLS/SRTP 等安全与媒体传输协议)。


6. HTTP/3 为什么基于 UDP:QUIC 在做什么?

一句话:QUIC 想要“像 TCP 一样可靠 + 像 UDP 一样灵活(易升级、低握手成本)”。

你可以把 QUIC 理解为“把 TCP 的很多能力搬到用户态,并与 TLS 深度融合”,再借助 UDP 作为“可被网络转发的载体”。它带来的常见收益包括:

  • 更低的建连成本(握手更快,细节取决于是否复用已有密钥/会话)。
  • 更好的多路复用体验:减少传统 TCP 层面某些阻塞带来的影响(尤其在丢包时的体验差异)。
  • 更容易迭代:在用户态协议里更新,比内核里的 TCP 更灵活。

想看 HTTP 版本演进脉络可以参考:HTTP 版本演进


7. 前端常见技术到底跑在谁上面?

把“前端常见协议/技术 → 传输层”的映射记住,排障会快很多:

  • HTTP/1.1、HTTP/2:通常是 TCP(再叠加 TLS 就是 HTTPS)。
  • HTTP/3QUIC over UDP
  • WebSocketTCP(本质是一次 HTTP Upgrade 后在同一条 TCP 连接上双向通信)。
  • SSETCP(因此要注意字节流导致的消息粘连/截断问题)。
  • WebRTC:多为 UDP 优先(媒体传输追求低延迟)。
  • DNS:传统上多为 UDP;但在响应较大/需要可靠性时也会用 TCP。另外浏览器还可能使用 DoH(DNS over HTTPS,走 HTTP/TCP 或 HTTP/3/UDP)

8. 一个小实验:用 Node 感受“字节流 vs 数据报”

先说结论

同样是“发两次字符串”,TCP 端可能一次 data 事件就收到拼在一起的内容;UDP 端通常会收到两条独立的 message

浏览器环境无法直接创建 TCP/UDP Socket;这里用 Node 做演示更直观。

8.1 TCP:两次 write,不等于两次 data

TCP 服务器(示例):

import net from 'node:net';

net
.createServer((socket) => {
socket.on('data', (chunk) => {
console.log('TCP 收到:', chunk.toString());
});
})
.listen(9000, () => console.log('TCP server on :9000'));

TCP 客户端(示例):

import net from 'node:net';

const socket = net.createConnection({port: 9000}, () => {
socket.write('A');
socket.write('B');
socket.end();
});

你可能会看到服务端打印一次 AB,也可能分两次打印 AB(取决于时机与缓冲),这就是“字节流无边界”。

8.2 UDP:一次 send,对应一条 message(但可能丢)

UDP 服务器(示例):

import dgram from 'node:dgram';

const server = dgram.createSocket('udp4');
server.on('message', (msg) => console.log('UDP 收到:', msg.toString()));
server.bind(9001, () => console.log('UDP server on :9001'));

UDP 客户端(示例):

import dgram from 'node:dgram';

const client = dgram.createSocket('udp4');
client.send('A', 9001);
client.send('B', 9001, () => client.close());

UDP 更像“投递两封信”:接收端按“封”收到;但在真实网络下,信可能丢、可能顺序颠倒。


9. 常见误区纠正

  1. “UDP 一定比 TCP 快”:不一定。UDP 只是少了握手/重传等机制;一旦你在应用层补齐可靠性、拥塞控制,复杂度和开销也会上来(比如 QUIC)。
  2. “TCP 就不会丢包”:网络层仍然可能丢包,只是 TCP 会尽力重传让应用“看起来没丢”(但代价是更高延迟/更久等待)。
  3. “TCP 没有丢包所以不需要超时/重试”:应用层仍可能遇到连接断开、服务端崩溃、代理超时等问题,依然需要合理的超时与重试策略。

10. 总结

  • TCP:可靠、按序、面向连接、字节流,适合“必须完整正确”的场景。
  • UDP:轻量、无连接、数据报,适合“更关注实时”的场景(但要接受丢包/乱序,或在上层补齐能力)。
  • 前端常见映射:HTTP/1.1/2 & WebSocket & SSE → TCP;HTTP/3(QUIC) & WebRTC 媒体 → UDP 为主。

面试高频问答

Q1:TCP 和 UDP 的核心区别是什么?

TCP 面向连接、可靠、按序、字节流;UDP 无连接、尽力而为、可能丢/乱序、数据报有边界。

Q2:为什么说 TCP 是“字节流”,这会带来什么问题?

TCP 不保留应用层消息边界:发送两次不等于接收两次,可能粘在一起或被拆开。
解决思路通常是自己做协议:定长包、分隔符、长度字段(Length-Prefix)等。

Q3:UDP 完全不可靠吗?还能用于“可靠传输”吗?

UDP 本身不保证可靠,但可以在上层实现可靠机制(序号、ACK、重传、窗口、拥塞控制等)。QUIC 就是典型例子。

Q4:为什么 DNS 常用 UDP?什么时候会用 TCP?

UDP 开销小、一次请求/响应模型简单。
当响应较大、需要可靠传输、或某些特定场景(如区域传送)时会用 TCP。现代浏览器也可能走 DoH/DoT(本质走 HTTPS/TLS)。

Q5:为什么实时音视频更倾向用 UDP?

实时场景更怕“晚到”,旧数据晚到价值不大;TCP 的重传和按序交付可能放大延迟抖动。UDP 更灵活,允许丢弃过期数据并用抖动缓冲/FEC 等手段优化体验。

Q6:HTTP/3 为什么不直接用 TCP,而要用 UDP?

HTTP/3 依赖 QUIC。QUIC 借助 UDP 在用户态实现“可靠 + 加密 + 多路复用”等能力,并降低建连成本、提升在丢包时的体验,且更容易迭代升级。

Q7:WebSocket 是 TCP 还是 UDP?为什么?

WebSocket 基于 TCP:先通过 HTTP Upgrade 建立连接,之后在同一条 TCP 连接上做全双工通信,保证消息按序到达(但仍要注意应用层心跳与断线重连)。

Q8:前端怎么判断当前请求走的是 HTTP/2 还是 HTTP/3?

一般可在浏览器 DevTools 的 Network 面板查看协议列(不同浏览器展示略有差异)。如果看到 h2 多半是 HTTP/2;如果看到 h3/quic 则是 HTTP/3(QUIC over UDP)。