TCP流量控制,拥塞控制

TCP的流量控制

RTT算法

在TCP超时重传机制中,Timeout的设置对于重传非常重要:

  • 设长了,重发就慢,丢了老半天才重发,没有效率,性能差。
  • 设短了,会导致可能并没有丢就重发。于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。

而且,这个超时时间在不同的网络环境下不同,必须动态设置。为此,TCP引入了RTT(Round Trip Time,环回时间):一个数据包从发出去到回来的时间。这样,发送端就大约知道正常传输需要多少时间,据此计算RTO(Retransmission TimeOut,超时重传时间)。 听起来似乎很简单:在发送方发包时记下t0,收到接收方的Ack时记一个t1,于是RTT = t1 – t0。然而,这只是一个采样,不能代表网络环境的普遍情况。以下是一些RTT算法 ,具体原理就不介绍了。

RTT算法 : 经典算法,Karn / Partridge 算法,Jacobson / Karels 算法。

TCP滑动窗口

TCP使用滑动窗口(Sliding Window)做流量控制与乱序重排。乱序重排在TCP的重传机制中已经介绍,下面介绍流量控制。

TCP头里有一个字段叫Window(或Advertised Window),用于接收方通知发送方自己还有多少缓冲区可以接收数据。发送方根据接收方的处理能力来发送数据,不会导致接收方处理不过来,是谓流量控制。

TCP协议的发送缓冲区和接收缓冲区:
在这里插入图片描述
假设位置序号从左向右增长(常见的读、写缓冲区设计),解释一下:

  • 发送方:LastByteAcked指向收到的连续最大Ack的位置;LastByteSent指向已发送的最后一个字节的位置;LastByteWritten指向上层应用已写完的最后一个字节的位置。
  • 接收方:LastByteRead指向上层应用已读完的最后一个字节的位置;NextByteExpected指向收到的连续最大Seq的位置;LastByteRcvd指向已收到的最后一个字节的位置。可以看到NextByteExpected与LastByteRcvd中间有些Seq还没有到达,对应空白区。

据此在接收方计算AdvertisedWindow,在发送方计算EffectiveWindow:

  • 接收方在Ack中记录自己的AdvertisedWindow = MaxRcvBuffer – (LastByteRcvd - LastByteRead),随Ack回复到发送方。
  • 发送方根据Ack中的AdvertisedWindow值,需保证LastByteSent - LastByteAcked ≤ AdvertisedWindow,则窗口内剩余可发送的数据大小EffectiveWindow = AdvertisedWindow - (LastByteSent - LastByteAcked),以保证接收方可以处理。

TCP的拥塞控制

通信中的拥塞指:到达通信子网中某一部分的分组数量过多,使得该部分网络来不及处理,以致引起这部分乃至整个网络性能下降的现象,严重时甚至会导致网络通信业务陷入停顿即出现死锁。

为什么要进行拥塞控制?假设网络已经出现拥塞,如果不处理拥塞,那么延时增加,出现更多丢包,触发发送方重传数据,加剧拥塞情况,继续恶性循环直至网络瘫痪。可知,拥塞控制与流量控制的适应场景和目的均不同。

TCP拥塞检测的方法

  • 典型的TCP只有在断定拥塞发生的情况下,才会采取相应的行动。 推断是否出现拥塞,通常看是否有丢包情况发生。
  • 其他拥塞探测方法,包括时延测量和显式拥塞通知(ECN),使得TCP能在丢包发生前检测拥塞。

rwnd与cwnd

  • rwnd是用于流量控制的窗口大小,即上述流量控制中的AdvertisedWindow,主要取决于接收方的处理速度,由接收方通知发送方被动调整。
  • cwnd是用于拥塞处理的窗口大小,取决于网络状况,由发送方探慢启动算法查网络主动调整。

介绍流量控制时,我们没有考虑cwnd,认为发送方的滑动窗口最大即为rwnd。实际上,需要同时考虑流量控制与拥塞处理,则发送方窗口的大小不超过min{rwnd, cwnd}。下述4种拥塞控制算法只涉及对cwnd的调整,同介绍流量控制时一样,暂且不考虑rwnd,假定滑动窗口最大为cwnd;但读者应明确rwnd、cwnd与发送方窗口大小的关系。

4种拥塞控制算法

拥塞发生前,可避免流量过快增长拖垮网络;拥塞发生时,唯一的选择就是降低流量。主要使用4种算法完成拥塞控制:

  1. 慢启动
  2. 拥塞避免
  3. 拥塞发生
  4. 快速恢复

算法1、2适用于拥塞发生前,算法3适用于拥塞发生时,算法4适用于拥塞解决后。

慢启动算法

慢启动算法(Slow Start)作用在拥塞产生之前:对于刚刚加入网络的连接,要一点一点的提速,不要妄图一步到位。如下:

  1. 连接刚建好,初始化cwnd = 1(当然,通常不会初始化为1,太小),表明可以传一个MSS大小的数据。
  2. 每收到一个ACK,cwnd++,线性增长。
  3. 每经过一个RTT,cwnd = cwnd * 2,指数增长(主要增长来源)。
  4. 还有一个ssthresh(slow start threshold),当cwnd >= ssthresh时,就会进入拥塞避免算法。

因此,如果网速很快的话,Ack返回快,RTT短,那么,这个慢启动就一点也不慢。下图说明了这个过程:
在这里插入图片描述

拥塞避免算法

前面说过,当cwnd >= ssthresh(通常ssthresh = 65535)时,就会进入拥塞避免算法(Congestion Avoidance):缓慢增长,小心翼翼的找到最优值。如下:

  • 每收到一个Ack,cwnd = cwnd + 1/cwnd,显然,cwnd > 1时无增长。
  • 每经过一个RTT,cwnd++,线性增长(主要增长来源)。

慢启动算法主要呈指数增长,粗犷型,速度快(“慢”是相对于一步到位而言的);而拥塞避免算法主要呈线性增长,精细型,速度慢,但更容易在不导致拥塞的情况下,找到网络环境的cwnd最优值。

拥塞发生时的算法

慢启动与拥塞避免算法作用在拥塞发生前,采取不同的策略增大cwnd;如果已经发生拥塞,则需要采取策略减小cwnd。那么,TCP如何判断当前网络拥塞了呢?很简单,如果发送方发现有Seq发送失败(表现为“丢包”),就认为网络拥塞了。

丢包后,有两种重传方式,对应不同的网络情况,也就对应着两种拥塞发生时的控制算法:

  1. 超时重传。TCP认为这种情况太糟糕,调整力度比较大:

     ssthresh = cwnd /2
     cwnd = 1,重新进入慢启动快速恢复算法(网络糟糕,要慢慢调整)
    
  2. 快速重传。

     ssthresh = cwnd /2
     cwnd = cwnd /2,进入快速恢复算法(网络没那么糟,可以快速调整,见下)
    

快速恢复算法

如果触发了快速重传,即发送方收到至少3次相同的Ack,那么TCP认为网络情况不那么糟,也就没必要提心吊胆的,可以适当大胆的恢复。为此设计快速恢复算法(Fast Recovery),下面介绍TCP Reno中的实现。

  1. cwnd = ssthresh + 3 * MSS (尝试一步到位)
  2. 重传重复Ack对应的Seq
  3. 如果再收到该重复Ack,则cwnd++,线性增长(缓慢调整)
  4. 如果收到了新Ack,则cwnd = ssthresh ,然后就进入了拥塞避免的算法了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值