传输层协议:TCP与UDP的区别、TCP三次握手与四次挥手、流量控制与拥塞控制
核心原理:TCP与UDP的定位差异
传输层位于网络层之上,为应用进程提供端到端的逻辑通信。TCP(Transmission Control Protocol)与UDP(User Datagram Protocol)是两种截然不同的传输协议,其本质差异源于设计目标:TCP追求可靠、有序、面向连接的数据传输,而UDP追求低延迟、无连接、尽力而为的报文交付。这种差异直接决定了它们适用的应用场景——TCP适合文件传输、网页访问、邮件等对数据完整性要求高的场景;UDP适合实时音视频、在线游戏、DNS查询等对时延敏感且允许少量丢包的场景。
核心区别速览:
| 对比维度 | TCP | UDP |
|---|---|---|
| 连接状态 | 面向连接(需建立/释放连接) | 无连接(直接发送) |
| 可靠性 | 可靠传输(确认、重传、排序) | 不可靠(无确认、无重传) |
| 数据边界 | 字节流,无边界 | 报文,保留边界 |
| 传输效率 | 较低(头部20字节+开销) | 较高(头部8字节) |
| 流量/拥塞控制 | 支持(滑动窗口+拥塞算法) | 不支持 |
| 典型应用 | HTTP、FTP、SMTP、SSH | DNS、RTP、DHCP、在线游戏 |
方法流程:TCP三次握手与四次挥手
TCP通过三次握手(Three-Way Handshake)建立连接,确保双方收发能力正常并同步初始序列号。整个过程涉及三个关键报文:SYN、SYN+ACK、ACK。客户端首先发送SYN报文并进入SYN_SENT状态;服务端收到后回复SYN+ACK并进入SYN_RCVD状态;客户端再发送ACK确认,双方进入ESTABLISHED状态。值得注意的是,第三次握手可以携带应用数据,从而减少一次RTT的开销。
连接释放采用四次挥手(Four-Way Wavehand),因为TCP连接是全双工的,每个方向必须独立关闭。主动关闭方发送FIN报文进入FIN_WAIT_1;被动方回复ACK进入CLOSE_WAIT,此时主动方进入FIN_WAIT_2;被动方应用层准备好后发送FIN进入LAST_ACK;主动方回复ACK后进入TIME_WAIT,等待2MSL后彻底关闭。TIME_WAIT状态的存在是为了保证最后一个ACK能到达对方,同时让旧连接的重复报文在网络中自然消失。
抓包验证技巧:使用 tcpdump -i eth0 tcp port 8080 或 Wireshark 过滤 tcp.flags.syn == 1,可以直观观察到握手报文的序列号变化。三次握手中,双方各自维护一个初始序列号(ISN),通过确认号(ACK Number)实现可靠同步。
案例/场景:流量控制与拥塞控制的协同工作
流量控制解决的是发送方与接收方之间的速度匹配问题,通过滑动窗口机制实现。接收方在TCP头部通告自己的接收窗口(rwnd),发送方据此调整发送速率,避免接收方缓冲区溢出。而拥塞控制解决的是网络链路的承载能力问题,发送方维护一个拥塞窗口(cwnd),实际发送窗口取 min(rwnd, cwnd)。两者协同,既保护接收方,也保护网络。
以一次典型的HTTP文件下载为例:连接建立后,发送方进入慢启动阶段,cwnd从1个MSS(最大报文段长度)开始,每收到一个ACK指数增长,直到达到慢启动阈值(ssthresh)。随后进入拥塞避免阶段,cwnd线性增长。若发生超时重传,ssthresh降为当前cwnd的一半,cwnd重置为1,重新慢启动;若收到三个重复ACK,则触发快速重传,ssthresh减半,cwnd减半后进入快速恢复阶段。这一系列机制共同保证了网络在高负载下不会崩溃。
# 查看当前TCP拥塞控制算法(Linux)
sysctl net.ipv4.tcp_congestion_control
# 输出示例:net.ipv4.tcp_congestion_control = cubic
# 查看TCP连接状态统计
ss -s
# 输出示例:
# TCP: 12 (estab 5, closed 0, orphaned 0, timewait 2)
误区/复盘:常见理解偏差与实战教训
- 误区一:认为UDP一定比TCP快。实际上,在可靠网络环境下,TCP的批量数据传输效率可能更高,因为TCP支持连续发送和窗口自适应;UDP的“快”主要体现在无连接建立延迟和头部开销小,但应用层需要自行处理丢包和乱序。
- 误区二:混淆流量控制与拥塞控制。流量控制是端到端的接收方能力通告(rwnd),拥塞控制是发送方对网络状态的推测(cwnd)。两者独立变化,最终发送窗口取二者较小值。
- 误区三:忽略TIME_WAIT状态的影响。高并发短连接场景下,服务端大量socket处于TIME_WAIT状态会占用端口资源。可通过开启
net.ipv4.tcp_tw_reuse和tcp_timestamps来复用TIME_WAIT连接,但需谨慎评估安全性。 - 误区四:认为三次握手一定比两次更可靠。两次握手无法防止已失效的连接请求突然到达服务端而建立无效连接;三次握手通过第三次ACK确认,确保服务端知道客户端已准备好,避免资源浪费。
实战复盘:某视频直播平台曾因UDP丢包导致画面卡顿,工程师误以为增加带宽即可解决。实际上,UDP没有拥塞控制,当网络出现拥塞时,UDP流量会持续注入,反而加剧网络恶化,甚至挤占TCP流量。最终方案是在应用层实现基于延迟的码率自适应,并限制UDP发送速率,才恢复服务质量。这说明即使使用UDP,也必须设计应用层的拥塞感知机制。
理解TCP与UDP的本质差异、掌握三次握手与四次挥手的完整状态迁移、区分流量控制与拥塞控制的不同作用域,是进行网络编程和故障排查的基础。在实际项目中,应根据业务需求选择协议,并针对协议特性设计相应的优化策略。