拥塞窗口(cwnd)与慢启动阈值(ssthresh)详解


1. 拥塞窗口(Congestion Window, cwnd)

  • 定义
    发送方维护的一个变量,表示当前允许一次性发送的未确认数据量(单位:MSS,最大报文段大小)。

  • 例如:cwnd=4 表示可以连续发送4个MSS的数据,无需等待ACK。

  • 作用

  • 动态调整发送速率,避免网络过载(拥塞控制的核心)。

  • 与接收方的通告窗口(rwnd)共同决定实际发送窗口:
    **实际窗口 = min(cwnd, rwnd)**。

  • 初始值

  • 通常初始为 1 MSS(如RFC 5681建议),现代Linux内核可能初始为 10 MSS


2. 慢启动阈值(Slow Start Threshold, ssthresh)

  • 定义
    一个动态阈值,用于区分慢启动阶段拥塞避免阶段

  • cwnd < ssthresh 时,TCP进入指数增长的慢启动阶段。

  • cwnd >= ssthresh 时,TCP转为线性增长的拥塞避免阶段。

  • 初始值

  • 通常设为一个大值(如 65535字节),在首次拥塞事件后更新为:
    **ssthresh = max(已发送未确认数据量 / 2, 2 MSS)**。


3. 两者协同工作流程

  1. 连接建立时
  • cwnd = 1 MSSssthresh = 初始大值(如Linux默认 10 MSS)。
  1. 慢启动阶段(cwnd < ssthresh)
  • 每收到一个ACK,cwnd += 1 MSS指数增长(1→2→4→8…)。
  1. 拥塞避免阶段(cwnd >= ssthresh)
  • 每RTT(往返时间)内,cwnd += 1 MSS线性增长(如8→9→10…)。
  1. 拥塞发生时
  • 超时重传:重置 cwnd = 1 MSSssthresh = cwnd/2,重新慢启动。
  • 快速重传(3个重复ACK):ssthresh = cwnd/2cwnd = ssthresh + 3 MSS,进入快速恢复

4. 关键区别

特性 拥塞窗口(cwnd) 慢启动阈值(ssthresh)
作用 控制当前发送速率 划分慢启动与拥塞避免的边界
初始值 1 MSS 或 10 MSS 大值(如Linux默认10 MSS)
变化触发 每ACK(慢启动)或每RTT(拥塞避免) 仅在拥塞事件发生时更新
调整规则 指数/线性增长 拥塞时设为当前cwnd的一半

5. 实例说明

假设初始 cwnd=1 MSSssthresh=8 MSS

  1. 慢启动阶段
  • ACK1 → cwnd=2
  • ACK2 → cwnd=4
  • ACK4 → cwnd=8(达到ssthresh
  1. 拥塞避免阶段
  • 每RTT → cwnd=9cwnd=10
  1. 发生拥塞(丢包)
  • 设新ssthresh=cwnd/2=5cwnd=1,重新慢启动。

6. 为什么需要这两个参数?

  • cwnd:实时控制发送速率,避免压垮网络。
  • ssthresh:记录历史拥塞点,避免重复触发慢启动的“激进”增长。

通过两者的配合,TCP在高吞吐低拥塞之间取得平衡。

在TCP拥塞控制机制中,当拥塞窗口(cwnd)小于阈值(ssthresh, 慢启动阈值)时,拥塞窗口会以指数增长(Exponential Growth)的方式快速扩大。这一阶段称为慢启动(Slow Start),尽管名字叫“慢启动”,实际窗口增长非常迅速。


关键过程解析

  1. 慢启动阶段(Slow Start)
  • 条件cwnd < ssthresh
  • 窗口增长规则:每收到一个ACKcwnd增加 1个MSS(最大报文段大小)
  • 例如:初始cwnd=1,接下来的窗口变化为:1 → 2 → 4 → 8 → 16…(指数增长)。
  • 目的:快速探测网络可用带宽。
  1. 拥塞避免阶段(Congestion Avoidance)
  • 条件cwnd >= ssthresh
  • 窗口增长规则:改为线性增长(每RTT增加1个MSS)。
  1. 触发拥塞的响应
  • 超时重传(Timeout):直接重置cwnd=1ssthresh减半,重新进入慢启动。
  • 重复ACK(Fast Retransmit):触发快速重传,cwndssthresh调整为当前值的一半,进入快速恢复(Fast Recovery)

图示窗口增长

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
拥塞窗口 (cwnd)


│线性增长(拥塞避免)
│↗
│↗
│↗
│↗
│↗
│↗
│↗
│↗ 指数增长(慢启动)
│↗
└─────────────────────────▶ 时间
ssthresh阈值

为什么叫“慢启动”?

  • 历史原因:相比最初的TCP实现(直接发送整个窗口数据),这种“逐步试探”的方式显得“慢”。
  • 实际行为:窗口增长是指数级的(比线性更快),但初始窗口较小(如cwnd=1)。

总结

  • cwnd < ssthresh指数增长(慢启动)
  • cwnd >= ssthresh线性增长(拥塞避免)
  • 核心目标:在避免拥塞的前提下,高效利用网络带宽。