TCP(传输控制协议)和 UDP(用户数据报协议)是计算机网络中最核心的两个传输层协议。它们最本质的区别可以用一句话概括:TCP 是大包大揽的"完美主义者"(靠谱但重),UDP 是追求极致的"速度狂人"(轻量但随缘)。
一、 核心区别对比表
我们可以通过 7 个关键维度来直观对比它们:
|--------|-------------------------------------|------------------------------|
| 维度 | TCP (Transmission Control Protocol) | UDP (User Datagram Protocol) |
| 是否面向连接 | 是。必须先建立连接(三次握手)。 | 否。无连接,知道 IP 和端口拔腿就发。 |
| 可靠性 | 极其可靠。不丢包、不重复、不乱序。 | 不可靠。尽力交付,丢了不管,不管顺序。 |
| 传输形式 | 面向字节流(无边界,会粘包/拆包)。 | 面向报文(保留边界,发多大收多大)。 |
| 传输速度 | 慢(有复杂的确认机制和拥塞控制)。 | 极快(没有多余的握手和控制逻辑)。 |
| 首部开销 | 大。固定头部占 20 字节(最多 60 字节)。 | 小。固定头部仅占 8 字节。 |
| 通信对象 | 一对一(点对点单播)。 | 支持一对一、一对多、多对多(广播/组播)。 |
| 典型应用场景 | 网页浏览(HTTP)、文件传输(FTP)、邮件(SMTP)。 | 音视频通话、实时游戏、视频直播、DNS 查询。 |
二、 深入理解:它们是如何工作的?
TCP 为什么靠谱?(为了可靠付出的代价)
TCP 承诺"只要你把数据交给我,我拼了命也会完整无误地送到对方手里"。为了这个承诺,它实现了非常复杂的机制:
-
握手与挥手: 连数据还没发,就要先通过"三次握手"确认双方收发能力正常;断开时要"四次挥手"。
-
确认应答( ACK )与超时重传: 发送方发的每个包,接收方都要回一个 ACK(确认收到)。如果发送方等了一会儿没收到 ACK,就会认为丢包了,立马重新发送。
-
流量控制 与拥塞控制: 自动探测网络堵不堵、对方的缓冲区满不满。如果网络太卡或者对方快转不过来了,TCP 会自动降速。
代价: 这些复杂的控制机制导致了它的延迟比 UDP 高,且耗费更多的系统资源。
UDP 为什么快?(极致的极简主义)
UDP 的核心思想是"我只负责搬运,送不送得到看天意"。它没有任何多余的动作:
-
没有建立连接的开销,没有确认机制,没有重传,没有流量控制。
-
它就像发短信或者扔飞镖,应用层给它一个 1KB 的包,它加上 8 字节的头就直接扔进网络。
代价: 网络一抖动它就丢包,数据到了接收端也可能会乱序。
三、 传输形式的区别:字节流 vs 报文
这也就是我们之前聊到"粘包/拆包"时的核心根源:
-
TCP 是"面向 字节流 ": 客户端连续发送消息 A 和消息 B,TCP 会把它们拆散或者揉成一团,变成一串连贯的字节倒进管道。接收方只知道管道里源源不断有水流(字节)出来,必须自己去划分 A 和 B 的界限。
-
UDP 是"面向报文": 客户端发一个消息 A(500字节),UDP 就打包成一个独立的 UDP 报文发走;紧接着发消息 B(300字节),又是一个独立的报文。接收方调用
recvfrom()时,一次正好读出一个完整的消息 A,UDP 绝对不会发生 粘包 问题。
四、 如何选择?(场景应用)
在实际工程(比如写 C++、Qt 或网络服务器)中,选择哪个协议完全取决于你的业务容忍度。
-
选 TCP 的场景: 对数据准确性要求 100%,能容忍一定延迟。
- 例子: 传输一个压缩包、下载一个软件、浏览网页。如果丢掉一个比特位,整个解压就会失败,网页可能就乱码了。
-
选 UDP 的场景: 对实时性要求极高(延迟要低),能容忍少量丢包。
- 例子: 射击游戏、语音通话。游戏里你开了一枪,这个数据包必须在几毫秒内传到服务器。如果网络抖动卡了一下丢包了,TCP 会选择"卡住并重传旧包",这就导致你画面卡死;而 UDP 选择"不管旧包,直接发最新的位置包",在游戏里的表现仅仅是角色轻微"瞬移"了一下,但整体是流畅的。
技术前沿补充: 现在的很多现代协议(比如谷歌的 QUIC 协议,也就是 HTTP/3 的底层),为了同时获得"UDP 的快"和"TCP 的靠谱",选择基于 UDP 传输,但在应用层自己写代码实现了类似 TCP 的可靠确认和重传机制。这在当前的实时音视频(WebRTC)和现代网络开发中非常流行。