5月29日 00:10

TCP 拥塞控制的四个算法是什么?超时重传和快重传怎么区分?

TCP 拥塞控制有四个算法:慢启动、拥塞避免、快重传、快恢复。核心思想是"先试探再加码"——不清楚网络能承受多少时就少发,确认没问题再加速;一旦发现拥塞就立刻降速。控制对象是 cwnd(拥塞窗口),和 rwnd 取较小值作为实际发送窗口。

追问

慢启动为什么叫"慢"?明明指数增长很快

"慢"是相对没有拥塞控制的情况——TCP 早期一上来就发满窗口,容易打爆网络。慢启动从 cwnd=1 MSS 开始,每收到一个 ACK 就 +1 MSS,一个 RTT 内翻倍(1→2→4→8→16)。看起来快,但初始只有 1 MSS,比直接发满窗口保守得多。cwnd 到达 ssthresh 后切换到拥塞避免的线性增长(每 RTT +1 MSS),不再翻倍。ssthresh 的初始值通常很大,第一次丢包后才设为 cwnd/2。

3 个重复 ACK 为什么就重传?不等超时吗?

等超时太慢了。RTO 通常是几百毫秒到几秒,而 3 个重复 ACK 说明后续包已经到了,只是中间那个丢了——网络还在工作,只是丢了一个包。快重传收到第 3 个重复 ACK 就立即重传,不用等 RTO,恢复速度差了一个数量级。为什么是 3 个不是 1 个?因为偶尔乱序也会产生重复 ACK,1 个就重传太激进,3 个基本确认是丢包。

超时重传和快重传的处理有什么不同?

超时重传意味着网络可能严重拥塞——连 ACK 都回不来了,所以处理更激进:ssthresh = cwnd/2,cwnd 直接降到 1 MSS,重新慢启动。快重传说明网络还通着(后续包到了),只是丢了一个包,所以处理温和:ssthresh = cwnd/2,cwnd 降到 ssthresh 而不是 1,进入快恢复。这就是为什么快重传后不回慢启动——丢一个包不代表网络崩溃。

BBR 和传统拥塞控制有什么不同?

传统算法(Reno/Cubic)基于丢包判断拥塞——丢包就降速,不丢就加速。问题是在高延迟高丢包的网络(无线、跨国)里,丢包不一定是拥塞,可能是链路本身的特性,传统算法会白白降速。BBR(Google 2016 年提出)不看病包,直接测量带宽和 RTT,把发送速率调整到带宽-延迟积(BDP),目标是把管道填满但不溢出。实测:YouTube 启用 BBR 后跨洲链路吞吐量提升 10-100 倍。

写段代码

python
# 模拟慢启动和拥塞避免的 cwnd 变化 def simulate_cwnd(ssthresh=16, max_rtt=20): cwnd = 1 # 初始 1 MSS for rtt in range(1, max_rtt + 1): if cwnd < ssthresh: cwnd *= 2 # 慢启动:指数增长 phase = "慢启动" else: cwnd += 1 # 拥塞避免:线性增长 phase = "拥塞避免" print(f"RTT {rtt:2d}: cwnd={cwnd:3d} MSS [{phase}]") simulate_cwnd()
标签:TCP