TCP—拥塞控制简介

来源:互联网 发布:java future实现原理 编辑:程序博客网 时间:2024/05/23 22:27

本系列文章是博主学习TCP协议以来的个人笔记。博主不能保证本文所述

内容绝对正确,所以请读者抱着怀疑的态度阅读本博客内的文字。如果读

者因本博客内的文字造成损失,本人无力负责。如果有任何谬误或者问题,

希望读者不吝赐教。

 
TCP实现可靠传输有赖于其超时/重传机制,但这种机制并非总是那么可靠。
设想广域网上网络拥塞,某些报文传输延时较长(但并未丢失),此时发送端
重传计时器超时,于是重传报文,导致网络上存在两个同样的报文,很显然
降低了带宽资源的利用率,加剧网络拥塞程度,类似火上浇油。

因此TCP需要拥塞控制能力,jacobson,1988描述了一种拥塞避免算法,后
来成为了当时的标准。该算法认为分组在传输过程中因损坏而导致丢失的可
能性非常小,因此分组丢失就意味着网络拥塞。有两个现象表明网络发生拥
塞它们是:  1.发生超时   2.收到重复确认
尽管慢启动算法和拥塞避免算法是两个目的不同的独立算法,但是拥塞避免
算法的实现借助了慢启动算法。曾记否?慢启动算法在通告窗口的基础上增
加了一个拥塞窗口cwnd,通告窗口由接受端使用,而拥塞窗口由发送端使用。
发送方每次所能发送的最大报文段为cwnd和通告窗口大小的最小值。拥塞控
制算法在cwnd窗口的基础上又增加了一个称之为慢启动门限的变量ssthresh,
其初始值为65536.
当拥塞发生时,ssthresh被设置为当前通告窗口大小的一半(但最小为2个报文
段),如果是超时引起的则cwnd变为1。当新的数据被对方确认时,就增加cwnd
.但是如何增加取决于我们采用的是慢启动算法还是拥塞避免算法。这里的规则
是当cwnd小于ssthresh时,执行慢启动算法;当cwnd大于ssthresh时,执行
拥塞避免算法。当cwnd增加到拥塞发生时的通告窗口大小的一半时,慢启动过
程终止,接着转为执行拥塞避免。
这里cwnd在慢启动过程,仍然是以指数的方式增长1,2,4......。如果是拥塞避免
过程,则cwnd以每个往返(RTT)1满尺寸数据段的速度递增。直到网络出现拥
塞为止,显然这是一种加性增长。

基于超时的拥塞检测需要有一个好的RTT算法,然而影响RTT的因素很多,而且
由于RTT具有动态特性,在实际中不易得到较准确的RTT。因此基于收到重复ACK
的拥塞检测在用得相对较多。快速重传算法就是基于重复ACK提出的,它规定如
果收到连续的3个或者3个以上的重复ACK则非常有可能是一个报文丢失了,于是
发送端重传丢失的报文段,无需等到重传定时器溢出。接下执行的不是慢启动算
法而是拥塞避免算法—这就是快速恢复算法。
那么在这种情况下为什么没有执行慢启动算法呢?这是出于效率的考虑,由于只
有在收到了另一个报文的时候,接收端才会发送重复的ACK,因此收到重复的ACK
不仅告诉我们一个分组丢失了,而且提示我们刚接到的那个报文已经离开了网络。
也就是说,收发两端仍然有数据流动,因此不必执行慢启动来突然减少数据流动。

快速传送和快速恢复算法经常像下面那样一起实现。
1. 当第三个重复ACK收到时,设置ssthresh为不大于max (FlightSize / 2, 2*SMSS) 
       FlightSize是仍在网络中传送的数据量,SMSS是发送端MSS
2. 重传丢失的数据段并设置cwnd的值为ssthresh+3*SMSS。这将人为地按已
        经离开网络的报文段数目(3)和接收端缓冲数据量来扩充拥塞窗口。
3. 对每个接收到的附加的重复ACK,将cwnd增大SMSS字节。这将人为地扩充
        拥塞窗口以反映已经离开网络的附加数据段。
4. 发送一个数据段,如果cwnd和接收端的通知窗口的值允许的话。
5. 当下一个确认新数据的ACK到达时,设定cwnd值为ssthresh(步骤1设置的
      值)。这称作“deflating"窗口。这个ACK必须是步骤1触发的重发引起的确认,
      重发之后一个RTT(在接收端有了次序紊乱的数据段的情况下,它可能一会儿
      就到达)。另外,此ACK应该确认丢失数据段和第三个ACK副本期间的数据段
     ,如果它们一个也没有丢失的话。


原创粉丝点击