TCP拥塞控制与滑动窗口

拥塞控制

拥塞控制就是防止过多的数据注入网络中,我们常见的方法有:

  • 慢开始与拥塞避免
  • 快重传和快恢复
  • 随机早期检测RED

拥塞窗口cwnd(congestion window): 拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口,另外考虑到接受方的接收能力,发送窗口可能小于拥塞窗口。

RTT(Round-Trip Time):往返时延。是指数据从网络一端传到另一端所需的时间。

慢开始与拥塞避免

在慢开始的阶段,首先会以很小的cwnd发出报文,而每收到一次确认ACK回执后,将cwnd+1:
慢开始
明显的,我们可以看到在网路空闲的情况下,cwnd会指数的向上增长,而持续的慢开始会导致窗口过大引起阻塞,我们还需要设置一个慢开始门限ssthresh状态变量:

  • 当cwnd<ssthresh时,使用慢开始算法。
  • 当cwnd>ssthresh时,改用拥塞避免算法。
  • 当cwnd=ssthresh时,慢开始与拥塞避免算法任意。

而拥塞避免算法是每在一个RTT时间内将cwnd+1,将cwnd的增长曲线减缓。

当判断网络出现拥塞(没有收到确认)时,无论是慢开始还是拥塞避免的过程中,我们都会将ssthresh/2,并将cwnd归1重新开始慢加速。
拥塞阻塞

快重传和快恢复

快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。
快重传

而重传完后还会执行快恢复的算法:

  • 当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半。但是接下去执行拥塞阻塞。
  • 考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将cwnd设置为ssthresh的大小,然后执行拥塞避免算法。如下图:
    快重传和快恢复

随机早期检测RED

以上的拥塞避免算法并没有和网络层联系起来,实际上网络层的策略对拥塞避免算法影响最大的就是路由器的丢弃策略。在简单的情况下路由器通常按照先进先出的策略处理到来的分组。当路由器的缓存装不下分组的时候就丢弃到来的分组,这叫做尾部丢弃策略。这样就会导致分组丢失,发送方认为网络产生拥塞。更为严重的是网络中存在很多的TCP连接,这些连接中的报文段通常是复用路由路径。若发生路由器的尾部丢弃,可能影响到很多条TCP连接,结果就是这许多的TCP连接在同一时间进入慢开始状态。这在术语中称为全局同步。全局同步会使得网络的通信量突然下降很多,而在网络恢复正常之后,其通信量又突然增大很多。

为避免发生网路中的全局同步现象,路由器采用随机早期检测(RED:randomearly detection)。该算法要点如下:

  • 使路由器的队列维持两个参数,即队列长队最小门限min和最大门限max,每当一个分组到达的时候,RED就计算平均队列长度。
  • 平均队列长度小于最小门限——把新到达的分组放入队列排队。
  • 平均队列长度在最小门限与最大门限之间——则按照某一概率将分组丢弃。
  • 平均队列长度大于最大门限——丢弃新到达的分组。
    随机早期检测RED

滑动窗口

滑动窗口协议是传输层进行流控的一种措施,接收方通过通告发送方自己的可以接受缓冲区大小(这个字段越大说明网络吞吐量越高),从而控制发送方的发送速度,不过如果接收端的缓冲区一旦面临数据溢出,窗口大小值也会随之被设置一个更小的值通知给发送端,从而控制数据发送量(发送端会根据接收端指示,进行流量控制)。

这里再说明下ACK报文:

  • 期望接收到的下一字节的序号n
  • 当前的窗口大小m

而滑动窗口协议如图:
滑动窗口