上一篇我已经总结了: TCP 滑动窗口和定时器,所以这一篇我继续总结一下 TCP 的拥塞控制。

重要概念

慢速启动

当建立连接时,发送端用一个很小的值初始化窗口,一开始是 1 的,不过后面根据经验值改为 4 作为初始值。然后发送端发送初始化大小窗口的数据,数据包经过一个往返时间之后被确认,对于每一个在重传定时器超市前就接收到的数据段,发送端的拥塞窗口都会增加一个段。这个时候,因为增加了一段和收到了前一个段的响应,所以一下可以发送 2 个段,所以,没经过一个 RTT,拥塞窗口就增加了一倍。虽然这个算法被叫做慢速启动,但其实它一点也不慢。

线性增长

为了保持对慢速启动的控制,发送端为每个链接维持了一个 慢启动阈值,当拥塞窗口超过 慢启动阈值 时,每次 RTT 只会增加一个数据段(之前是成倍得增加),当遇到超时时,慢启动阈值 被设置为当前拥塞窗口的一半。慢启动阈值 一开始的默认值被设置成任意高(当然,不同的拥塞算法有不同的设置策略,例如 Tahoe 一开始设置为 64 KB)

快速重传

如果确认一个包已经超时,如果使用重传定时器,可能效率会比较低,因为它必须保守。发送端有一个快速方法来识别它的包已经丢失,因为在接收端,如果丢失数据包的后续数据包到达接收端时,他们会触发发送端返回确认,这些确认都将携带着相同的确认号,成为 重复确认。发送端每次收到重复确认后,很可能另一个包已经到达了接收端而丢失的那个包还没有出现。

虽然 TCP 可能因为数据段的传输路径不同而导致包的乱序,但是,通常情况下这样的情况并不常见,所以 TCP 很随意得将三次相同的 重复确认 认定为该数据段丢失。

快速恢复

快速重传的机制比较慢,每次出现超时之后都需要从 1 个数据段开始,为了加强效率,因此有了 快速恢复,它的目的就是保持拥塞窗口上运行确认时钟,使得在有一个新的阈值或者快速重传时可以把拥塞窗口减少到一半,而不是直接从初始值开始。为了实现这个效果,就需要对重复计数累计(包括 3 次重复计数),累计重复计数到网络中未确认的分段数是当前拥塞窗口值,这大概需要半个 RTT 即可。

在快速恢复一个 RTT 之后,重复计数的那个分段也应该被接收端接收,在这个时刻,重复确认流将停止,快速恢复模式退出,拥塞窗口将被设置为新的慢启动阈值,并开始按照线性增长开始。

拥塞控制的改进

选择重传

在重复确认中,发送端无法知道接收端具体丢了哪些包,需要重发那些包,所以 TCP 就增强了一个 选择确认 功能,通过选择确认,接收端最多可以向发送端响应 3 段接收到的数据包,这样发送端就可以有选择得发送丢失的包,从而减小网络压力:

显示拥塞通知

显式拥塞通知(ECN,Explicit Congestion Notification) 是 IP 层的机制,它主要是用来通知主机发生了拥塞,在 TCP 中,当建立连接的时候,发送端会设置 ECE 和 CWR 标志位,告诉对方支持 ECN 机制,双方协商表示都支持 ECN 之后,该 TCP 连接就会使用 ECN。

每个写到 TCP 端的数据包都会在 IP 头上打上标记,表示支持 ECN,当遇到网络拥塞时,支持 ECN 的路由器就会设置 ECN 标志,然后接收端接受到之后,就会使用 ECE(ECN Echo)标志位给发送端发通知,告诉发送端数据包经历了拥塞。发送端就会通过拥塞窗口减少(CWR,Congestion Window Reduced)标志位告知接收端已经收到拥塞信号了。

当发送端接收到拥塞通知知道,就会采取重复确认一样的拥塞控制。

Reference