# TCP 拥塞控制

所谓拥塞控制就是防止过多的数据注入网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制和流量控制都是太那个个控制发送方发送数据的速率来达到效果的。

区别在于:拥塞控制是让网络能够承受现有的网络负荷,它是一个全局性的过程,设计所有主机,路由器以及网络传输性能有关的所有因素。而流量控制往往是指点对点的通信量的控制,即接收端控制发送端,即抑制发送端发送数据的速率,以便使接收端来得及接收。

因此,发送方在确定发送报文段的速率时,既要根据接收方的接收能力,又要从全局考虑不要使网络发送拥塞,因此,TCP 协议要求发送方维护两个窗口:

  • 接收窗口 rwnd,接收方根据目前接收缓存大小所设定的窗口值
  • 拥塞窗口 cwnd,发送方根据自己估算的网络拥塞程度设置的窗口值,反映了网络的当前容量。

发送窗口的上限取得是接收窗口 rwnd 和拥塞窗口 cwnd 中较小的一个,即 min (rwnd,cwnd)

接受窗口根据 TCP 报文首部的窗口字段确定,拥塞窗口怎么维护呢?为了更好地对传输层进行拥塞控制,给出了下面四种算法:慢启动、拥塞避免、快重传、快恢复

# 拥塞控制算法

# 慢启动算法

在 TCP 刚连接好,开始发送 TCP 报文段时,先令将拥塞窗口(cwnd)设置为一个较小的值(通常为 1),在每收到一个对新的报文段确认后,再将 cwnd 加 1,慢开始算法,每经过一个传输轮次(即往返 RTT),拥塞窗口 cwnd 就会加倍,即呈指数形式增加,当慢开始算法把拥塞窗口 cwnd 增大到一个阈值 ssthresh,改用拥塞避免算法。

# 拥塞避免算法

拥塞避免算法的做法是:发送端的拥塞窗口 cwnd 每经过一个往返 RTT,按线性规律缓慢增长。

# 网络拥塞的处理

当网络出现拥塞,不管是在慢开始阶段还是拥塞避免阶段,只要发送方检测到超时事件发送,就要把慢开始阈值 ssthresh 设置为出现拥塞时的发送方 cwnd 的一半(但不能小于 2),然后将拥塞窗口 cwnd 重新设置为 1,执行慢开始算法。这样做的目的是迅速减少主机发送到网络中的分组数,使得发送拥塞的路由器有足够的时间把队列中积压的分组处理完毕。

慢开始和拥塞避免算法实现过程如图所示:
tcp-crowding

注意:在慢开始阶段,若 2cwnd>ssthresh, 则下一个 RTT 的 cwnd 应等于 ssthresh,而不是 2cwnd,即 cwnd 不能超过 ssthresh 值

# 快重传和快恢复

快重传和快恢复算法是对慢开始和拥塞避免算法的改进

  1. 快重传
    当发送方连续收到三个重复的 ACK 报文,直接重传对方尚未收到的报文段,而不必等待那个报文段设置的重传计时器超时。
  2. 快恢复
    当发送端收到连续三个冗余 ACK 时,就执行 “乘法减少” 算法,把慢开始阈值 ssthresh 设置为出现拥塞时发送方 cwnd 的一半。与慢开始将拥塞窗口 cwnd 设置为 1 的不同之处,它把 cwnd 的值设置为慢开始阈值 ssthresh 减半后的数值,然后执行拥塞避免算法,使拥塞窗口缓慢线性增大。

实现过程如下图所示:
tcp-fast

# 总结

发送方发送窗口的实际大小由流量控制和拥塞控制共同决定,流量控制窗口 rwnd 由接收方在 TCP 报文段首部窗口字段提供,而拥塞控制窗口由发送方对当前网络环境的预估,结合慢开始和拥塞避免或者更优算法快传和快恢复算法来进行拥塞控制。最终发送方实际的发送窗口大小是由 rwnd 和 cwnd 中较小的那一个确定的。

参考文献:https://juanha.github.io/2018/05/05/tcp/