TCP 拥塞控制 | 计算机基础
TCP 的拥塞控制由 4 个核心算法组成:慢开始、 拥塞避免、快速重传和快速恢复。
慢开始
发送方维持一个叫作拥塞窗口 cwnd (congestion window)的状态变量(注意区分发送窗口)。 拥塞窗口的大小取决于网络的拥塞程度, 并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口,另外考虑到接受方的接收能力,发送窗口可能小于拥塞窗口。
慢开始算法的思路就 是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。慢开始的原理如下所述:
- 当主机开始发送数据时,如果立即将较大的发送窗口的全部数据字节都注入到网络中,那么由于不清楚网络的情况,有可能引其网络拥塞
- 比较好的方法是试探一下,即从小到大逐渐增大发送端的拥塞控制窗口数值
- 在刚刚开始发送报文段时可先将拥塞窗口 cwnd 设置为最大报文段长度 MSS 的数值。在每收到一个对新报文段确认后,将拥塞窗口增加至多 一个 MSS 的数值,当 rwind 足够大的时候,为了防止拥塞窗口 cwind 的增长引起网络拥塞,还需要另外一个变量,即慢开始门限 ssthresh
因为收到一个 ack 拥塞窗口就增加一个段,所以一次传输轮次之 后拥塞窗口就会加倍。
这就是指数增长($y=2^x$),和后面的拥塞避免算法的加法增长比较。
拥塞避免
为了防止 cwnd 增长过大引起网络拥塞,还需设置一个慢开始门限 ssthresh 状态变量。ssthresh 的用法如下:
- 当 cwnd < ssthresh 时,使用慢开始算法
- 当 cwnd > ssthresh 时,改用拥塞避免算法
- 当 cwnd = ssthresh 时,慢开始与拥塞避免算法任意
拥塞避免算法让拥塞窗口缓慢增长,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1 ,而不是加倍。拥塞控制具体过程如下所述:
- TCP 连接初始化,将拥塞窗口设置为1
- 执行慢开始算法,cwind 按指数规律增长,直到 cwind = ssthress 时,开始执行拥塞避免算法,cwnd 按线性规律增长
- 当网络发生拥塞,把 ssthresh 值更新为拥塞前 ssthresh 值的一半,cwnd 重新设置为 1,按照上个步骤执行
拥塞控制具体过程如下图所示。再次提醒这里只是为了讨论方便而将拥塞窗口大小的单位改为数据报的个数,实际上应当是字节数。
快速重传和快速恢复
快速重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方),而不要等到自己发送数据时捎带确认。快速重传算法规定,发送方只要一连收到 3 个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。
快速重传配合使用的还有快速恢复算法,有以下两个要点:
- 当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把 ssthresh 门限减半,但是接下去并不执行慢开始算法
- 考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开 始算法, 而是将 cwnd 设置为 ssthresh 的大小,然后执行拥塞避免算法,如下图所示
总结
TCP 拥塞控制窗口变化的原则是加法增大、乘法减小。可以看出 TCP 的该原则可以较好地保证流之间的公平性,因为一旦出现丢包,那么立即减半退避,可以给其他新建的流留有足够的空间,从而保证整个通信的公平性。
参考
《图解 TCP/IP》
《后台开发:核心技术与应用实践》
TCP 拥塞控制 | 计算机基础