TCP的拥塞控制
拥塞(congestion)
在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。
拥塞控制
拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。
如图所示,横坐标是提供的负载(offered load),代表单位时间内输入给网络的分组数目。纵坐标是吞吐量(throughput),代表单位时间内从网络输出的分组数目。
理想状态:在吞吐量饱和之前,网络吞吐量应等于提供的负载,故吞吐量曲线是45度的斜线。但当提供的负载超过某一限度时,由于网络资源受限,吞吐量不再增长而保持为水平线,即吞吐量达到饱和。
实际状态:随着提供的负载的增大,网络吞吐量的增大速率逐渐减小。也就是说,在网络吞吐量还未达到饱和时,就已经有一部分的输入分组被丢弃了。当网络的吞吐量明显的小于理想的吞吐量时,网络就进入了轻度拥塞的状态。当提供的负载达到某一数值时,网络的吞吐量反而随提供的负载的增大而下降,这时网络就进入了拥塞状态。当提供的负载继续增大到某一数值时,网络的吞吐量就下降到零,网络无法工作,这就是所谓的死锁(deadlock)。
几种拥塞控制的方法
慢开始(slow-start)
发送方维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态的在变化。
慢开始的算法是这样的:
如果立即把大量的数据字节注入到网络,那么就有可能引起网络阻塞,所以由小到大逐渐增大发送窗口数值,即由小到大逐渐增大拥塞窗口数值。
开始先设置cwnd = 1,发送第一个报文段M1,接收方收到后确认M1。发送方收到对M1的确认后,把cwnd从1增大到2,于是发送方接着发送M2和M3两个报文段。接收方收到后发回对M2和M3的确认。发送方每收到一个对新报文段的确认,就使发送方的拥塞窗口加1,因此发送方收到两个确认后,cwnd就从2增大到4,并可以发送M4-M7共4个报文段。因此使用慢开始算法后,每经过一个传输轮次,拥塞窗口cwnd就加倍。
为了防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限ssthresh状态变量。用法如下
当cwnd<ssthresh时,使用上述的慢开始算法。
当cwnd>ssthresh时,停止使用慢开始算法而改用拥塞避免算法。
当cwnd=ssthresh时,既可使用慢开始算法,也可使用拥塞避免算法。
拥塞避免算法(congestion avoidance)
算法思路:
让拥塞窗口cwnd缓慢增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。这样,拥塞窗口cwnd按线性规律缓慢增长,比慢开始短发的拥塞窗口增长速率缓慢很多。
实例:
(1)为了便于理解,途中的窗口单位不使用字节而使用报文段的个数。慢开始门限的初始值设置为16个报文段。即ssthresh=16。
(2)在执行慢开始算法时,拥塞窗口cwnd的初始值为1。拥塞窗口cwnd随着传输轮次按指数规律增长。当拥塞窗口cwnd增长到慢开始门限ssthresh时,就改为执行拥塞避免算法,拥塞窗口按线性增长。
(3)假定拥塞窗口的数值增长到24时,网路出现超时。更新后的ssthresh值变为12(即为24的一半),拥塞窗口再设置为1,并开始慢开始算法。当cwnd=ssthresh=12时改为执行拥塞避免算法,拥塞窗口按线性规律增长。
快重传(fast retransmit)
算法思路:
接收方每收到一个失序的报文段后就立即发出重复确认而不要等待自己发送数据时才捎带确认。如图所示,接收方收到了M1和M2后都分别发出了确认。现假定接收方没有收到M3,但是收到了M4。显然,接收方不能确认M4,因为M4是失序的报文段。根据可靠传输原理,接收方可以什么都不做,也可以在适当时机发送一次对M2的确认。但是在快重传的规定里,接收方应及时发送对M2的重复确认,这样做可以让发送方及早知道报文段M3没有达到接收方。发送方接着发送M5和M6。接受方收到后,也还要再次发出对M2的重复确认。这样,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段M3,不必等到重传计时器到期。
快恢复(fast recovery)
算法思想:
当发送方连续收到三个重复确认时,不执行慢开始算法,由于发送方现在认为网络很有可能没有发生拥塞,因此,与慢开始不同之处是现在不执行慢开始算法,而是把cwnd值设置为慢开始门限ssthresh减半后的数值,然后开始执行拥塞避免算法,使拥塞窗口缓慢地线性增大。如图所示,TCP Reno版本就是在快重传之后采用快恢复算法,而不是采用慢开始算法。