- TCP/UDP 核心区别 :TCP 是面向连接、可靠、有序、带流量 / 拥塞控制 的字节流协议;UDP 是无连接、不可靠、无序、无控制的数据报协议,二者是传输层的「两极」,无优劣之分,只看场景适配;
- 适用场景:UDP 选「实时性优先、可容忍少量丢包」的场景(如直播、游戏);TCP 选「可靠性优先、需有序无丢包」的场景(如 Web、文件传输);
- 高性能服务器选 TCP 的核心原因 :绝大多数高性能服务器的业务本质是「可靠数据传输」 (如 HTTP 接口、RPC 调用、数据库交互),且 TCP 的「可控性」能通过
epoll+非阻塞IO+主从Reactor等技术优化,弥补其开销,实现「高可靠 + 高并发」的平衡。
一、UDP 和 TCP 的核心区别
TCP 和 UDP 是 TCP/IP 协议簇传输层的两大核心协议 ,二者的设计目标完全相反,所有区别都源于「是否需要保证传输可靠性」
|-----------|-----------------------------------------------------------------------------|---------------------------------------------------------------------------------|
| 对比维度 | TCP(传输控制协议) | UDP(用户数据报协议) |
| 核心定位 | 可靠的、面向连接的字节流协议 | 不可靠的、无连接的数据报协议 |
| 连接性 | 面向连接 :通信前必须通过三次握手 建立连接,通信后通过四次挥手关闭连接 | 无连接:通信前无需建立连接,直接发送数据报,无连接管理开销 |
| 可靠性 | 强可靠 :通过「序列号 + 确认号 + 超时重传 + 快重传」保证数据无丢失、无重复 | 弱可靠:无确认、无重传,数据发出去后不管是否到达,内核不保证交付 |
| 有序性 | 保证有序:接收方会根据序列号对乱序数据重排,按发送顺序交给应用层 | 不保证有序:数据报独立传输,可能乱序到达(先发的包可能后到) |
| 传输方式 | 字节流传输 :无消息边界,发送方send(100字节),接收方可能recv(50字节)+recv(50字节)(粘包 / 半包根源) | 数据报传输 :有明确消息边界,发送方sendto(1个数据报),接收方recvfrom()一次只能拿到完整的 1 个数据报,不会粘包 / 半包 |
| 流量控制 | 支持:基于滑动窗口 + 通告窗口(rwnd),匹配发送方和接收方速率,防止接收方缓冲区溢出 | 不支持:无流量控制,发送方不管接收方处理能力,可能导致接收方缓冲区溢出丢包 |
| 拥塞控制 | 支持:基于拥塞窗口(cwnd)+ 慢启动 / 拥塞避免 / 快重传 / 快恢复,匹配发送方和网络速率,防止网络崩溃 | 不支持:无拥塞控制,发送方以恒定速率发送数据,网络拥塞时直接丢包 |
| 首部开销 | 大:固定首部 20 字节,可选字段最多扩展到 60 字节 | 小:固定首部仅 8 字节(源端口 + 目的端口 + 长度 + 校验和),开销极低 |
| 适用场景 | 可靠性优先、需有序传输的场景 | 实时性优先、可容忍少量丢包的场景 |
| 编程复杂度 | 高:需处理粘包 / 半包、连接管理、超时重传等问题 | 低:无需处理连接和边界问题,数据报独立传输,代码极简 |
- 「速度」不是绝对的 :很多人认为 UDP 比 TCP 快,其实只有在网络通畅、无丢包的理想场景下,UDP 的速度优势才明显;如果网络拥塞,UDP 会大量丢包,应用层需要自己实现重传,此时 UDP 的实际速度可能比 TCP 更慢;
- 「连接」的本质差异 :TCP 的连接是内核级的双向连接 ,内核会为每个连接维护序列号、窗口大小、超时计时器等状态;UDP 的通信是无状态的,内核不维护任何连接信息,发送方甚至不知道接收方是否在线。
二、UDP 和 TCP 的适用场景
TCP 和 UDP 的选型没有绝对的优劣 ,只看业务的核心诉求------ 是「要可靠有序」,还是「要低延迟实时」。
1. UDP 的适用场景(实时性优先,可容忍丢包)
UDP 的核心优势是 「低延迟、低开销、高实时性」 ,适合那些「少量丢包不影响业务,但延迟高会严重影响体验」的场景,典型案例:
(1)音视频直播 / 实时通话
- 比如抖音直播、腾讯会议、王者荣耀语音聊天;
- 核心诉求:延迟必须低于 200ms,否则会出现音画不同步、卡顿;
- 选型原因:UDP 的传输延迟比 TCP 低一个量级(无握手、无重传、无拥塞控制);少量数据包丢失只会导致画面轻微花屏、语音短暂杂音,用户完全可容忍;而 TCP 的超时重传会导致「卡顿 - 重传 - 更卡顿」的恶性循环。
(2)网络游戏
- 比如英雄联盟、和平精英的实时走位、技能释放;
- 核心诉求:玩家操作指令必须实时同步,延迟超过 100ms 就会出现「走位漂移」「技能放歪」;
- 选型原因:UDP 能保证指令的实时传输,少量丢包可通过「预测补位」(比如根据玩家前一帧走位预测当前位置)解决;而 TCP 的重传延迟会让游戏完全无法玩。
(3)DNS 域名解析
- 比如浏览器访问
www.baidu.com时的 DNS 查询; - 核心诉求:查询要快,单次请求响应;
- 选型原因:DNS 查询是「一次请求 - 一次响应」的短交互,UDP 的 8 字节首部开销远小于 TCP 的 20 字节;即使丢包,客户端也会立即重发,总耗时比 TCP 三次握手更短。
(4)IoT 物联网设备通信
- 比如智能手环、传感器的数据上报;
- 核心诉求:设备算力 / 带宽有限,需低开销传输;
- 选型原因:UDP 的代码实现简单,内核开销小,适合算力薄弱的嵌入式设备;传感器的温度、湿度数据即使丢包,下次上报即可补充,无需可靠传输。
(5)广播 / 组播通信
- 比如局域网内的设备发现、视频会议的多端推送;
- 核心诉求:一对多传输;
- 选型原因:UDP 天然支持广播(发给局域网所有设备)和组播(发给特定组的设备),而 TCP 是点对点连接,无法实现一对多传输。
2. TCP 的适用场景(可靠性优先,需有序无丢包)
TCP 的核心优势是 「可靠、有序、可控」 ,适合那些「数据丢失 / 乱序会导致业务崩溃,延迟高一点可以接受」的场景,典型案例:
(1)Web 服务(HTTP/HTTPS)
- 比如浏览器访问网页、电商平台下单支付;
- 核心诉求:数据必须完整有序,比如网页的 HTML 代码、支付的订单数据,丢一个字节都会导致页面乱码、订单失败;
- 选型原因:TCP 的可靠性保证了网页数据、支付数据的完整传输;即使延迟高一点,用户也能接受(比如网页加载慢 100ms)。
(2)文件传输
- 比如 FTP 文件下载、微信传文件、网盘备份;
- 核心诉求:文件必须 100% 完整,不能有任何字节丢失或错误;
- 选型原因:TCP 的校验和、重传机制能保证文件的完整性;如果用 UDP 传输文件,少量丢包就会导致文件损坏,无法打开。
(3)数据库 / 远程调用
- 比如 MySQL 的客户端 - 服务端通信、微服务的 RPC 调用;
- 核心诉求:指令和数据必须可靠有序 ,比如
INSERT语句、转账请求,丢包会导致数据不一致,乱序会导致业务逻辑错误; - 选型原因:TCP 的有序性保证了数据库指令的执行顺序,可靠性保证了数据的一致性,这是业务的生命线。
(4)邮件 / 消息推送
- 比如 SMTP 邮件发送、微信消息推送;
- 核心诉求:消息必须送达,不能丢失;
- 选型原因:TCP 的确认机制保证了消息能准确到达接收方;而 UDP 无法保证,可能导致邮件 / 消息丢失。
三、高性能服务器为什么选 TCP?
1. 高性能服务器的业务本质是可靠数据传输
绝大多数高性能服务器的核心业务,都对「数据可靠性」有硬性要求:
- 比如 Web 服务器:必须保证 HTML/CSS/JS 代码完整传输,否则页面无法正常渲染;
- 比如 RPC 服务器:必须保证调用参数和返回结果准确无误,否则微服务之间的通信会出错;
- 比如支付服务器:必须保证订单数据、金额数据 100% 正确,否则会导致资金损失。
这些业务场景下,少量丢包都是不可接受的------UDP 的不可靠性会直接导致业务崩溃,而 TCP 的可靠性是业务的「生命线」。
2. TCP 的「可控性」强,能通过技术手段优化性能,弥补开销
很多人认为 TCP 的「连接管理、拥塞控制」是性能瓶颈,但在高性能服务器中,这些开销可以通过成熟的技术手段完全抵消,甚至实现「高可靠 + 高并发」的双赢:
(1)用「主从 Reactor+epoll ET」解决 TCP 的连接管理开销
- TCP 的三次握手、四次挥手是连接管理的核心开销,但muduo服务器采用「主 Reactor 主线程 + 从 Reactor 工作线程」架构:
- 主线程只负责监听连接事件、accept 建立连接,不处理任何业务逻辑,极致轻量化;
- 工作线程负责处理 IO 事件,通过 epoll ET 边缘触发 + 非阻塞 IO,实现一个线程处理数万 TCP 连接,完全抵消了连接管理的开销。
(2)用「长连接 + 连接池」减少 TCP 的握手开销
- TCP 的三次握手开销主要体现在「短连接」场景(比如 HTTP/1.0 的短连接,每次请求都要握手);
- 高性能服务器会采用 「TCP 长连接」:一个 TCP 连接可以处理数千个 HTTP 请求,大幅减少握手次数;
- 进阶优化:用连接池预创建一批 TCP 连接,供业务线程复用,彻底消除握手开销。
(3)用「HTTP/2 多路复用」解决 TCP 的队头阻塞问题
- TCP 的「队头阻塞」是传统痛点(一个连接上的请求串行执行,前一个请求慢会阻塞后续请求);
- 高性能服务器会支持HTTP/2 协议:在同一个 TCP 连接上,通过「流(Stream)」实现多路复用,多个请求并行传输,彻底解决队头阻塞问题,并发性能堪比 UDP。
(4)用「内核参数调优」提升 TCP 的传输效率
- 通过调整 Linux 内核的 TCP 参数(如
SO_REUSEADDR/SO_REUSEPORT、TCP_FASTOPEN、TCP_CONGESTION),可以大幅提升 TCP 的并发能力和传输效率:SO_REUSEADDR/SO_REUSEPORT:解决 TIME_WAIT 过多导致的端口占用问题,支持多进程监听同一个端口;TCP_FASTOPEN(TFO):实现 TCP 的 0-RTT 握手,减少连接建立延迟;TCP_CONGESTION:选择适合的拥塞算法(如 BBR),提升高带宽高延迟网络下的传输效率。
3. TCP 的可靠性是「内核实现」,应用层开发更高效
如果用 UDP 做高性能服务器,应用层需要自己实现可靠性机制(如序列号、确认、重传、拥塞控制),这会带来巨大的开发成本和维护成本:
- 比如要实现 UDP 的可靠传输,需要开发类似 TCP 的滑动窗口、超时重传、拥塞控制逻辑,这相当于「在应用层重新实现一个 TCP」;
- 而 TCP 的可靠性是Linux 内核原生实现 的,经过了数十年的工业级验证,稳定可靠,应用层只需要调用
recv()/send()即可,开发效率极高。
对于高性能服务器来说,开发效率和稳定性远比「极致的低延迟」更重要------TCP 的内核级可靠性,是工业级项目的最优选择。
4. TCP 的「流量控制 + 拥塞控制」是高并发的保障
高性能服务器需要支撑数万甚至数十万并发连接,此时网络的拥塞是不可避免的:
- TCP 的拥塞控制机制(慢启动、拥塞避免)会根据网络状态动态调整发送速率,防止网络崩溃;
- TCP 的流量控制机制(滑动窗口)会根据接收方的处理能力调整发送速率,防止接收方缓冲区溢出。
而 UDP 无拥塞控制,高并发下会大量丢包,导致业务性能暴跌 ------ 这也是高性能服务器不选 UDP 的重要原因。