跳到主要内容

5.7 TCP 的拥塞控制

当网络中数据量超过了设备的处理能力时,则称发生了网络拥塞。此时会导致数据报的丢失等情况,会导致数据传输效率降低,用户体验变差。

网络拥塞可以发生在网络的任何地方,包括但不限于路由器、交换机、用户端设备等。

(P241 5.8.2)当分组丢失后,TCP 会发生超时重传,此时 TCP 即认为可能发生了网络拥塞。即:只要出现了超时重传,TCP 就认为发生了网络拥塞

发送方维护一个拥塞窗口 cwnd(Congestion Window),真正的发送窗口取对方接收窗口我方拥塞窗口之间的最小值。此节中假设接收方接收窗口无限大,且数据发送时单向的,即此节仅讨论一个理想情况:发送窗口仅取决于拥塞窗口、接收方仅发送确认报文。

此节为讨论方便,拥塞发送窗口和发送的数据单位为 1×SMSS1 \times SMSS,即 1 个发送方最大报文段。

TCP 进行拥塞控制的算法有四种:慢开始(Slow-Start)和拥塞避免(Congestion Avoidance)快重传(Fast Retransmit)和快恢复(Fast Recovery)

TCP 实现必须实现慢开始、拥塞避免和 RTO 指数退避算法以完成拥塞控制。

相关词条:

  • 初始拥塞窗口 IW(Initial Window)

    初始拥塞窗口由 SMSS 决定:

    • SMSS>2190SMSS > 2190 时,拥塞窗口为 2×SMSS\bf{2 \times SMSS},且不得超过 2 个报文段
    • SMSS(1095,2190]SMSS \in (1095, 2190] 时,拥塞窗口为 3×SMSS\bf{3 \times SMSS}​,且不得超过 3 个报文段
    • SMSS(0,1950]SMSS \in (0, 1950] 时,拥塞窗口为 4×SMSS\bf{4 \times SMSS},且不得超过 4 个报文段

    并且:

    • 当握手过程中 SYN 和 SYN/ACK 报文丢失时,拥塞窗口初始值不得超过 1×SMSS\bf{1 \times SMSS},且不得超过 1 个报文段
  • 慢开始门限 ssthresh

    当拥塞窗口大小超过 ssthresh 时,则改用拥塞避免算法。ssthresh 初始值应当设置为任意高的值(例如最大可能的通告窗口的大小)。

5.7.1 慢开始和拥塞避免

RFC-5681 3.1)慢开始的主要思路是,从小到大逐渐改变拥塞窗口的数值,逐渐增加注入到网络中的数据。具体的:

  • 当拥塞窗口即 cwnd 不超过慢开始门限 ssthresh 时,使用慢开始算法,即每收到 1 个报文段的确认,则将 cwnd +1。慢开始实际含义为从慢速开始,实际 cwnd 大小的增长为指数型的。
  • cwnd 超过 ssthresh 时,使用拥塞避免算法,即每发送一个拥塞窗口的数据,并收到了所有发送的数据的确认(又称每经过一个 RTT),则将 cwnd +1
  • 当发生超时重传,即发生网络拥塞时,ssthresh 减小为当前 cwnd 的一半,并将 cwnd 重置为初始值,重新开始执行慢开始算法。

并且:

  • SYN 和 SYN/ACK 报文不得增加 cwnd

5.7.2 快重传和快恢复

RFC-5681 3.2)快重传和快恢复是建立在慢开始和拥塞避免机制基础之上,针对数据丢失的情况进行的优化

快重传要求接收方:

  • 不得进行延迟确认,即收到一个分组应立即发送确认
  • 不得进行选择确认,当分组乱序到达时,应对已连续正确收到的字节需要重复发送确认

快重传指当接收方收到对三个重复序号的 ACK 时,则视为发生了网络拥塞,此时立即进行重传,而非等待超时后重传。

快恢复指当发生网络拥塞时,在将 ssthresh 减小为当前 cwnd 的一半之后,将 cwnd 减小为 ssthresh,而非初始值,然后执行慢开始算法。