【TCP专题】TCP的拥塞控制

        TCP的拥塞控制是TCP当中的一个难点。很多人不太理解,为什么TCP有流控,还有个拥塞控制,这两个到底有啥区别?

        通过前面我们对TCP流控的简单介绍,因该能理解,流控主要是为了防止发送方发送流量过大导致接收方缓存区溢出的问题。而拥塞控制,则主要是受网络环境的影响。TCP也会观察网络的拥堵情况,如果网络拥塞严重的话,则将降低发送量,以缓解网络拥塞情况,这种行为属于TCP的拥塞控制

        大体的思路其实比较好理解,但是这句话其实就抛出了两个问题。

  • 第一个问题就是,TCP是如何判断此时网络环境拥塞的;
  • 第二个问题就是,TCP该如何去控制数据的发送量。(准确的说,如果一个TCP发送方感知从它到目的地之间的路径上没什么拥塞,则TCP发送方增加其发送速率;如果发送方感知沿着该路径有拥塞,则发送方就会降低其发送速率。)

TCP的拥塞判断

        那我们一个一个来,我们先来说下TCP到底是如何感知到此时网络中出现了拥塞的情况呢?

        其实拥塞判断的问题,我们前面在可靠性里面已经提及过一些。TCP将连接中出现的丢包行为,视为拥塞的表现。(这个其实很合理,一般数据包会丢失或者超时,大概率都是因为网络拥堵导致。)当然,丢包事件可以通过两种形式体现:

  • 其一就是数据包确认超时
  • 其二就是收到来自接受方发送的3个冗余ACK

TCP的拥塞控制

        因为发送方需要根据网络的拥塞情况来调控发送的速率,所以,发送方需要额外的维护一个变量,我们称为拥塞窗口(congestion window)--- cwnd。他和rwnd(接收窗口)一样,都可以对发送的字节数大小进行限制。也就是说,发送方发送多少数据,其实同时受rwnd和cwnd共同影响。发送方中,发出未收到确认的字节数必须小于或等于rwnd和cwnd中的最小值。所以,TCP发送方可以通过限制cwnd来间接的影响发送速率,实现调控效果。   

TCP拥塞控制算法

        当然,这个参数到底该如何使用,什么情况下该做什么样的调整,实际上是有专门的拥塞控制算法来进行操控的

        在了解具体的算法之前,我们需要明确一点思路,那就是太过保守的TCP传输反而会导致无法充分利用带宽。TCP被称为是自计时(self-clocking)的,就是因为他会通过确认来增大拥塞窗口。这个怎么理解呢?在不存在拥塞的情况中,TCP将收到的确认报文后会认为道路畅通,从而增加窗口的长度,其实就是在向上试探,以追求更高的传输速率。如果确认到达的慢,那么拥塞窗口的增加速率也会很慢;如果响应很及时,确认到达的很快,则拥塞窗口增加的也会很快。

        下来看下具体拥塞控制算法。这个算法主要包括三个部分 --- 慢启动,拥塞避免,快速恢复

慢启动(slow - start)

        TCP的连接在刚开始建立的时候,并不会直接以很大的传输速率来工作,因为并不清楚此时的网络情况,直接大量传输那不是胡闹嘛。通常,cwnd一开始会被设置成很小的一个值,一般等同于一个MSS,即一次只能发送一个数据报文段。但这个速率需要在短时间内提升起来,这就是慢启动的过程。

        慢启动的做法也是非常简单的,就是每收到一个新的ACK确认报文(重传的确认不算在内),就会增加一个MSS的大小。(这就是前面说的,TCP会根据确认来增大拥塞窗口)

所以,慢启动其实是一种快速提升传输速率的方式(不能被名字误导),因为其呈现的是指数增长。(图中拥塞窗口的数值单位为MSS)

        为了防止拥塞窗口cwnd增长过大造成网络拥塞,我们有不能一直处于慢启动状态。那他该如何停止呢?我们会设置一个慢启动门限(ssthresh)来做评定。

        当cwnd < ssthresh时,使用慢启动算法;

        当cwnd > ssthresh时,使用拥塞避免算法;

        当cwnd = ssthresh时,既可以使用慢启动算法,也可以使用拥塞避免算法。 

拥塞避免  

        那下来咱们就讨论下这个拥塞避免算法是如何计算的。其实拥塞避免的思路也是很简单的,就是不能再像之前一样,高速上升了,我们需要把上升的速度降缓。以前慢启动的时候,我们是一个RTT时间内(RTT就是前面说过的往返时间,如果cwnd是4个报文段,那RTT就是发送方连续发送4个报文段之后,并收到4个确认这个过程所消耗的时间。),收到几个ACK,cwnd就增加几个MSS。而到了拥塞避免中,一个RTT时间内,cwnd就只增长一个MSS。从慢启动的指数增长变为了线性增长,增长速度明显变缓了。

        注意,还是不能被这个名字所误导,拥塞避免也不是说就可以直接避免拥塞,而是通过降低窗口的增大速率而使网络不容易出现拥塞。

     

 (这里假设设定ssthresh为8)

快速恢复

        拥塞避免的增长到啥时候结束呢?如果没有出现拥塞的情况,那最好是可以一直增加下去的。但如果出现了拥塞,那这个增长就必须停止了。

        当然,拥塞判断前面咱们说了,有两种方法,出现这两种情况,我们做出的处理方案是不一样的。

        我们可以根据这张图片来进行分析。这里我们我们设置初始的ssthresh为16个报文段。一开始,cwnd执行慢启动算法,cwnd程指数上涨,很快就来到了ssthresh的门限值。也就是图中的①点。这里将结束慢启动,开始进入到拥塞避免算法。可以看出来增长速度明显变缓。

        变故出现再②点,假设此时的拥塞窗口是24(单位MSS),发生了超时重传的情况。这是我们判定网络出现拥塞的一种现象。这时候,我们会将ssthresh值设定为cwnd的一半(即ssthresh = cwnd / 2 = 24 / 2 = 12)。之后,将cwnd设置为1。之后,重新开始慢启动和拥塞避免的过程(他们之间的门限值就是12了。) --- 这是针对超时重传的设定。

        如果网络不会再发生拥塞,那这次的拥塞避免也应该一直执行下去,但是,变故又出现在了④点,此时cwnd是16。这时候,出现的是3次冗余ACK。这也是我们判定此时网络存在拥塞的一个依据,不过,在TCP眼中,这种情况并没有超时重传严重。因为此时并不一定网络真的存在拥塞,可能只是数据包丢失了。这时如果直接把cwnd降到1,感觉有点亏。所以,这种情况下(快速重传),我们采取的处理方案是 --- 使用快速恢复算法。

        快速恢复的做法也很简单,就是直接将ssthresh设置为cwnd的一半(即ssthresh = cwnd / 2 = 16 / 2 = 8),同时将cwnd也设置为8(相当于也降低了一半),之后,直接开始拥塞避免。

        这里需要注意一下,也有快速恢复实现会把初始的cwnd值在加3个MSS长度。相当于新的cwnd初始值为ssthresh + 3。(上面例子就是8 + 3 = 11)。这样做的理由是:既然发送方收到了3个重复的确认,就证明有3个分组已经离开了网络。这三个分组不再消耗网络资源而是停留在对方缓存中,所以,并没有堆积在网络里,那就可以适当的再加大一些窗口。

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

临界~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值