TCP拥塞控制

什么是拥塞控制

所谓的拥塞控制就是防止有过多的报文进入网络而造成路由器与链路过载的情况发生。它不同于流量控制,流量控制只是简单的通过接收端的接收缓存来设置接收窗口值,从而控制发送方的发送速率,而拥塞控制则是考虑整个网络传输的情况,通过动态改变TCP的拥塞窗口的值,从而动态调整发送方的传输速率。

拥塞窗口

拥塞窗口(cwnd)是发送方根据网络拥塞情况而得出的窗口值。而发送方的发送窗口的大小选择公式如下:

1
发送窗口=MIN(cwnd,rwnd);其中rwnd为接收窗口,cwnd为拥塞窗口

如何判断网络中出现了拥塞了?

只要网络中出现了“丢包事件”,发送方就认为在发送方到接收方的路径上的网络传输出现了拥塞。所谓的“丢包事件”,我们定义为:要么出现了超时,报么收到了3个冗余的ACK报文。

如何进行拥塞控制

在进行拥塞控制的过程中,常用的三种拥塞控制算法:

  • 慢启动
  • 拥塞避免算法
  • 快重传和快恢复

慢启动

拥塞窗口的增长

当一条TCP连接开始时,cwnd的值通常被设置为1个MSS。在慢启动的状态下,cwnd的值以1个MSS开始并且每个传输的报文段被确认就将cwnd的值翻倍。比如TCP向网络中发送的第一个报文段并且得到了确认。TCP的cwnd的值增加到:2个MSS,这样它就可以发送两个最长长度的报文段。如果这两个报文段都被确认了,则发送方对每个确认报文段都将拥塞窗口增加一个MSS,使得拥塞窗口的值变为:4个MSS。如此重复,在慢启动的状态下,cwnd以指数增长

结束慢启动的方式(下面介绍的Reno版TCP,如果是:Tahoe版TCP,没有快速重传和快速恢复)

出现了超时,进入拥塞避免状态

当TCP在传输报文中,出现了第一次超时时,马上启动一个状态变量:ssthresh,并且把它设置为cwnd/2,同时发送方会马上把cwnd从重新设置为:1个MSS,并重新开始慢启动过程。ssthresh是慢启动的阈值。cwnd在慢启动的状态呈指数增长,当cwnd的值超过或等于ssthresh时,不能在盲目的将cwnd翻倍了,而是进入拥塞避免状态,更为谨慎的增加cwnd的值

收到了3个冗余的ACK后,进入快重传和快恢复状态

如果发送方检测到了3个冗余的ACK后,这时TCP将cwnd的值减半,ssthresh的值也被更新为减半后的cwnd的值,然后,cwnd的值再加上3个MSS,最后,执行快速重传并进入快速恢复的状态。

拥塞避免算法

一旦进入了拥塞避免状态,cwnd的值将在一个RTT时间内只增加1个MSS。cwnd的值呈线性增长。

  • 在拥塞避免状态下,如果遇到了超时,TCP也会把状态变量:ssthresh的值设置为:cwnd/2,然后,把cwnd设置为1个MSS,并且进入慢启动状态。
  • 在拥塞避免状态下,如果是检测到了3个冗余的ACK后,这时TCP将cwnd的值减半,ssthresh的值也被更新为减半后的cwnd的值,然后,cwnd的值再加上3个MSS,最后,执行快速重传并进入快速恢复的状态。
    如下图,为超时的模拟图:
    image

快重传和快恢复

当发送方检测到了3个冗余的ACK后,将会马上重传丢失的分组,并且会执行快速恢复的算法。此时,cwnd的值是比原来的cwnd的值还多了3个的MSS后,它又会进入拥塞避免状态。如下图所示:
image

总结

TCP的拥塞控制在当前的网络传输中是占有很大地位的,因为它可以动态的调节发送方的传输效率,从而也间接的保证了TCP报文的可靠的传输。