TCP 拥塞控制详解(通俗版)
1. 先打个比方:TCP 就像送快递
想象你是一个快递员(TCP),负责把包裹(数据包)从仓库(服务器)送到客户(客户端)。但路上可能会堵车(网络拥塞),这时候你需要动态调整送货策略:
• 如果疯狂塞车还拼命发货 → 包裹全堵在路上,客户收不到(网络崩溃)。
• 如果太保守 → 送货效率太低(带宽浪费)。
• 目标:找到“刚刚好”的送货速度,让路不堵,客户也能快速收到货!
2. TCP 拥塞控制的四大核心算法
(1) 慢启动(Slow Start)—— “试探性发货”
• 初始状态:快递员不知道路况,先发 1个包裹(初始拥塞窗口 cwnd=1
)。
• 规则:每收到一个客户确认(ACK),窗口大小 翻倍(指数增长)。
• 比如:1 → 2 → 4 → 8 → 16…
• 何时停止:
• 遇到堵车(丢包)→ 触发拥塞避免。
• 达到阈值(ssthresh
)→ 切换为线性增长。
生动场景:
快递员第一次送货,客户说“收到1件了”,他下次就发2件;又说“收到2件”,下次发4件……直到客户喊“别发了!堵了!”(丢包)。
(2) 拥塞避免(AIMD)—— “稳一点”
• 规则:窗口大小 每次+1(线性增长),避免指数增长导致突然拥塞。
• 比如:16 → 17 → 18 → 19…
• 丢包时的反应:
• 直接砍半窗口(乘性减,cwnd = cwnd/2
),并更新 ssthresh
。
生动场景:
快递员发现某次发货后客户没确认(包裹丢了),立刻把发货量减半(比如从20件降到10件),然后慢慢+1件试探。
(3) 快速重传(Fast Retransmit)—— “客户催单”
• 问题:传统超时重传太慢(要等几秒)。
• 解决:如果客户连续收到 3个重复的包裹编号(如收到4号包裹后,又收到3个4号请求),快递员立刻重发丢失的包裹,不用等超时。
生动场景:
客户本来该收包裹5,但收到4、4、4(重复催单),快递员马上意识到“5丢了”,立刻补发5号包裹。
(4) 快速恢复(Fast Recovery)—— “边修路边送货”
• 规则:重传丢失包裹后,窗口大小 保持当前值(不重置为1),继续传输。
• 目的:避免像慢启动那样从零开始,提高效率。
生动场景:
快递员发现丢包后,不是回到每天只送1件,而是维持每天送10件(但更小心),边修路边送货。
3. 为什么这样设计?
• 公平性:所有TCP连接共享网络带宽,谁乱发数据谁吃亏(砍半惩罚)。
• 效率:慢启动快速探测带宽,拥塞避免避免过载。
• 健壮性:快速重传/恢复减少等待时间。
4. 实际抓包验证(Wireshark 示例)
用 Wireshark 抓包可以看到:
- 慢启动阶段:
cwnd
指数增长(窗口大小快速上升)。 - 丢包事件:出现重复ACK,触发快速重传。
- 拥塞避免:窗口线性增长。
5. 面试加分点
• 术语:cwnd
(拥塞窗口)、ssthresh
(慢启动阈值)、AIMD(Additive Increase Multiplicative Decrease)。
• 对比UDP:UDP不管拥塞(可能“堵死”别人),TCP是“文明人”。
• 现代改进:BBR算法(Google提出,用带宽和延迟估算替代丢包反馈)。
总结:TCP拥塞控制就是一套智能调速系统,像老司机开车——该猛踩油门时猛踩(慢启动),该点刹时点刹(拥塞避免),发现坑立马绕路(快速重传/恢复)! 🚗💨