第12章 UDP与TCP对比:可靠性、有序性、面向连接 vs 无连接、应用场景选择

说实话,TCP和UDP这两个协议,是网络编程里绕不开的坎儿。我刚开始学的时候,总觉得TCP是「正经协议」,UDP就是个「野路子」。后来踩过几次坑才明白——没有哪个更好,只有哪个更合适

这一章,咱们就把它们俩掰开揉碎了对比一下。我会结合自己这些年做项目的经验,聊聊什么时候该用TCP,什么时候UDP反而更香。

12.1 核心差异:一张表说清楚

先看个对比表格,心里有个底:

特性 TCP UDP
连接方式 面向连接(三次握手) 无连接(直接发)
可靠性 可靠传输(确认重传) 不可靠(丢包不重传)
有序性 保证数据按序到达 不保证顺序
传输效率 较低(头部20字节+控制开销) 较高(头部8字节)
流量控制 有(滑动窗口)
拥塞控制 有(慢启动、拥塞避免)
数据边界 流式(无边界) 报文(有边界)
典型应用 HTTP、FTP、SMTP DNS、视频流、游戏

这张表我建议你存一下。面试的时候,面试官问「TCP和UDP的区别」,你把这几个维度一摆,基本就稳了。

12.2 面向连接 vs 无连接

这是最根本的区别。

TCP是面向连接的。什么意思?就是通信之前,双方得先「握手」——三次握手建立连接,完了还得「挥手」——四次挥手断开连接。我当年第一次写TCP服务器,看到三次握手的抓包,觉得这玩意儿真讲究,像极了两个人见面先寒暄两句再谈正事。

UDP是无连接的。它不管对方在不在,直接把数据包扔出去。你想想看,就像你往人群里喊一嗓子,听见没听见全看缘分。我做过一个UDP日志收集系统,发送端只管发,接收端能收多少算多少。这种设计在丢包容忍度高的场景下,效率确实高。

核心理解:TCP像打电话——先拨号、接通、通话、挂断。UDP像寄明信片——写好地址扔邮筒,对方收不收得到,你管不着。

12.3 可靠性:TCP的「保险箱」vs UDP的「漂流瓶」

TCP的可靠性,说白了就是「确认+重传」机制。发送方发了数据,得等接收方回一个ACK。如果超时没收到ACK,TCP会自动重发。我调试过一个TCP文件传输程序,网络偶尔抖动一下,TCP默默重传了几次,文件最后完整到达——用户完全没感知。

UDP呢?它只管发,不负责。丢包了?那是你应用层的事。我曾经在一个视频监控项目里用UDP传视频帧,偶尔丢几帧画面花一下,但整体流畅度比TCP好太多。为什么?因为TCP发现丢包会重传,重传导致延迟,延迟导致画面卡顿——用户宁愿看到花屏,也不愿看到卡顿

我的经验:如果你做的是文件传输、数据库同步、远程控制这类「数据必须完整」的应用,老老实实用TCP。如果你做的是实时音视频、在线游戏、监控数据采集这类「可以丢一点但不能卡」的应用,UDP更合适。

12.4 有序性:TCP的「排队」vs UDP的「抢跑」

TCP保证数据按发送顺序到达。为什么能做到?因为每个TCP包都有一个序列号,接收方按序列号组装数据。如果包3先到了,包2还没到,TCP会先把包3缓存起来,等包2到了再一起交给应用层。

UDP不保证顺序。你发了包1、包2、包3,接收方可能先收到包3,再收到包1,最后收到包2。我做过一个UDP游戏协议,角色移动指令经常乱序——角色先走到B点,再走到A点,看起来就像瞬移。后来我在应用层加了个序列号,自己排序,才解决了这个问题。

注意:UDP的有序性问题,应用层必须自己处理。不要指望UDP帮你排好序——它没这个能力,也没这个义务。

12.5 应用场景选择:什么时候选谁?

这个问题,我直接给你一个决策流程:

  1. 数据必须完整到达吗?是→TCP,否→看第2条
  2. 延迟敏感吗?是→UDP,否→看第3条
  3. 数据量小且频繁吗?是→UDP(减少连接开销),否→TCP

举个例子:

  • Web浏览(HTTP):必须完整,延迟不太敏感→TCP
  • 视频直播:可以丢帧,延迟敏感→UDP
  • DNS查询:数据小,一次请求一次响应→UDP(默认)
  • 邮件发送(SMTP):必须完整,延迟不敏感→TCP
  • 在线游戏:位置更新可以丢,延迟敏感→UDP

我做过一个物联网项目,传感器每隔几秒上报一次温度数据。一开始用的TCP,结果设备多了,服务器连接数暴涨,内存吃紧。后来改成UDP,每个传感器发一个UDP包,服务器无状态接收,轻松扛住了十万级设备。你看,选对协议,事半功倍。

12.6 知识体系图

下面这张图,把TCP和UDP的核心差异和应用场景串起来了:

TCP vs UDP 知识体系 传输层协议 TCP 核心特性 • 面向连接(三次握手) • 可靠传输(确认重传) • 保证有序到达 典型应用 HTTP / FTP / SMTP / SSH UDP 核心特性 • 无连接(直接发送) • 不可靠(丢包不重传) • 不保证顺序 典型应用 DNS / 视频流 / 在线游戏

12.7 避坑指南

最后,分享几个我踩过的坑:

  • 别在UDP上实现TCP:我见过有人想在UDP上自己实现可靠传输、有序到达、拥塞控制——结果搞出来的东西既没有TCP稳定,又没有UDP高效。如果你需要可靠性,直接用TCP,别自己造轮子。
  • UDP缓冲区要设大一点:默认的UDP接收缓冲区可能只有几十KB,高并发场景下很容易丢包。我习惯把SO_RCVBUF设到1MB以上。
  • TCP的Nagle算法可能坑你:做实时交互时,Nagle算法会把小包攒起来再发,导致延迟飙升。我一般会设置TCP_NODELAY来禁用这个算法。
  • UDP的MTU问题:UDP包超过MTU(通常1500字节)会被分片,分片丢失会导致整个包重传。我习惯把UDP数据控制在1400字节以内。

一句话总结:TCP让你睡得安稳,UDP让你跑得更快。选哪个,看你更在乎什么。


公众号:蓝海资料掘金营,微信deep3321