• TCP之拥塞控制


    1、拥塞控制

    1.1、拥塞

      在某段时间,如果对网络中的某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要发生变化,这种情况叫阻塞。

    1.2、拥塞控制

      防止过多的数据注入到网络当中,这样可以使网络中的路由器或链路不致过载。在发送方维护一个虚拟的拥塞窗口,并利用各种算法使它尽可能的接近真实的拥塞点。(通过拥塞窗口处理网络拥塞现象的一种机制)
      拥塞控制的前提是当前网络能够承受现有的网络负荷;
      拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素;
      拥塞控制与流量控制的区别:流量控制往往是指点对点通信量的控制,是个端到端的过程;而拥塞控制所要做的就是控制发送端发送数据的速率,以便使接收端来得及接收,是一个全局性的过程;
      拥塞控制需要获得网络内部流量分布的信息。在实施拥塞控制之前,还需要在结点之间交换信息和各种命令,以便选择控制策略和实施控制。这样就产生了额外的开销。拥塞控制还需要将一些资源分配给各个用户单独使用,使得网络资源能更好的实现共享。

    1.3、拥塞控制机制

     

    1.4、拥塞控制的方法

      慢开始
      拥塞避免
      快重传
      快恢复

    2、慢开始

    2.1、算法原理

      当主机开始发送数据时,如果立即将大量数据字节注入到网络,那么就有可能因为不清楚当前网络的负荷情况而引起网络阻塞。所以,最好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。通常在刚刚发送报文段时,先把拥塞窗口cwnd设置为一个最大报文段MSS的数值。而在每收到一个新的报文段的确认后,把拥塞窗口增加至多一个MSS的数值。比如发了2个包之后收到2个确认,拥塞窗口就增大2+2=4,接下来是4+4=8,8+8=16... ... 这个过程增速很快,但基数很低,传输速度还是比较慢的,所以称之为慢开始(慢启动)过程。用这样的方法逐步增大发送方的拥塞窗口cwnd,可以使分组注入到网络的速率更加合理。(慢开始当中的“慢”并不是指cwnd的增长速率慢,而是在TCP开始发送报文段时先设置cwnd = 1,使得发送方在开始时只发送一一个报文段)。
      当rwnd足够大的时候,为了防止拥塞窗口cwnd的增长引起网络阻塞,还需要另外一个变量------慢开始门限ssthresh.
    • 当cwnd < ssthresh时,使用上述慢开始算法;
    • 当cwnd >ssthresh时,停止使用慢开始算法,改用拥塞避免算法;

    2.2、慢开始的局限性

      需要获得网络内部流量分布的信息,浪费可用的网络容量,需要额外的开销;
      估算合理的ssthresh值时并不容易,可能耗时较长: 
      • 接收端窗口rwnd,又称通知窗口(awnd),是接收端根据目前的接收缓存大小所许诺的最新窗口值,是来自接收端的流量控制。
      • 拥塞窗口cwnd是发送端根据自己估计的网络阻塞程度而设置的窗口值,是来自发送端的流量控制。
      • MSS是TCP数据包每次能够传输的最大数据分段,其中并不包括TCP首部。而MSS只出现在syn报文段当中。一般来说MSS的值在不分段的情况下越大越好(eg:一个外出接口的MSS值是MTU减去IP和TCP首部长度)

    3、拥塞避免

    3.1、算法原理

      让拥塞窗口cwnd缓慢的增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍,这样拥塞窗口cwnd按线性规律缓慢的增长,比慢开始算法的拥塞窗口增长速率缓慢的多。
      无论是慢启动算法还是拥塞避免算法,只要判断网络出现拥塞,就要把慢启动开始门限(ssthresh)设置为发送窗口的一半(>=2),cwnd设置为1,然后再使用慢启动算法,这样做的目的能迅速的减少网络当中的数据传输,使发生拥塞的路由器能够把队列中堆积的分组处理完毕。拥塞窗口是按照线性的规律增长

    3.2、控制过程

      TCP连接初始化,将拥塞窗口cwnd设置为1个报文段,即cwnd = 1;
      执行慢开始算法,cwnd按指数规律增长,直到cwnd == ssthresh时,开始执行拥塞避免算法,cwnd开始按照线性规律增长;
      当网络发生拥塞,把ssthresh值更新为拥塞前cwnd值的一半,cwnd重新设置为1,再开始慢开始算法;
      如下图为拥塞控制过程:
    • 在TCP连接进行初始化的时候,cwnd = 1,ssthresh = 16;
    • 在慢启动算法开始时,cwnd的初始值是1,每次发送方收到一个ACK拥塞窗口就增加1,当ssthresh == cwnd时,启动拥塞控制算法,拥塞窗口按照线性规律增长;
    • 当cwnd = 24时,网络出现超时,发送方收不到确认ACK,此时设置ssthresh = 12,设置cwnd = 1,然后开始慢启动算法,当cwnd = ssthresh=12,慢启动算法变为拥塞控制算法,cwnd按照线性速度增长

    3.3、AIMD(加法增大乘法减小)

      乘法减小:无论在慢启动阶段还是在拥塞控制阶段,只要网络出现超时,就是将cwnd置为1,ssthresh置为cwnd的一半,然后开始执行慢启动算法
      加法增大:当网络频繁出现超时情况时,ssthresh就下降的很快,为了减少注入到网络当中的分组数,而加法增大是执行拥塞避免算法后,是拥塞窗口缓慢的增大,以防止网络过早出现拥塞。
      这两个结合起来就是AIMD算法,是使用最广泛的算法。拥塞避免算法不能够完全避免网络拥塞,通过控制拥塞窗口的大小只能使网络不易出现拥塞。

    4、快重传

    4.1、算法原理

      一条TCP连接有时会因为等待重传计时的超时而空闲较长时间,慢开始和拥塞避免无法解决这类问题,因此提出了快重传和快恢复的拥塞控制方法。
      有时候网络拥塞很轻微,只有少量的包丢失。还有一些偶然因素,比如校验码不对,导致单个丢包。这两种丢包症状和严重拥塞时不一样,因为后续有包能正常到达。当后续的包到达接收方时,接收方会发现其Seq号比期望的大,所以它每收到一个包就Ack一次期望的Seq包,以此提醒发送方重传。当发送方收到3个或以上重复确认(Dup Ack)时,就意识到相应的包已经丢了,从而立即重传。这个过程称之为快重传。

    4.2、算法过程

      快重传算法要求首先接收方收到一个失序的报文段后立刻发出重复确认,而不要等待自己发送数据时才进行捎带确认,如下图:
      在上图中,接收方成功的接受了发送方发来的M1,M2并且分别发送了ACK,现在接收方没有收到M3,而收到了M4,显然接收方不能确认M4,因为M4是失序的报文段。如果根据可靠性传输原理接收方什么都不做,但是按照快速重传算法,在收到M4,M5等报文段的时候,不断重复的向发送方发送M2的ACK,如果接收方一连收到三个重复的ACK,那么发送方不必等待重传计时器到期,由于发送方尽早重传未被确认的报文段。

    5、快恢复

      采用快恢复算法时,慢开始只在TCP连接建立时和网络出现超时时才使用。
      当发送方连续收到三个重复确认时,执行“乘法减小”算法,慢启动门限减半,为了预防网络发生阻塞。
      由于发送方现在认为网络很可能没有发生阻塞,因此现在不执行慢启动算法,而是把cwnd值设置为慢启动门限减半后的值,然后开始执行拥塞避免算法,拥塞窗口cwnd值线性增大。
     

    6、总结

    • 没有拥塞时,发送窗口越大,性能越好。所以在带宽没有限制的条件下,应该尽量增大接收窗口的值;
    • 如果经常发生拥塞,那么限制发送窗口的大小反而能提高性能,因为即便万分之一的重传对性能的影响都很大;在很多操作系统上可以通过限制接收窗口的方法减少发送窗口;
    • 超时重传对性能的影响最大,因为它有一段时间(RTO)没有传输任何数据,而且拥塞窗口会被设为1个MSS,所以要尽量避免超时重传;
    • 快速重传对性能影响小一些,因为它没有等待时间,而且拥塞窗口减小的幅度也没那么大;
    • SACK和New Reno有利于提高重传效率,提高传输性能;
    • 丢包对极小文件的影响比大文件严重。因为读写一个小文件需要的包数据少,所以丢包时往往凑不足3个Dup Ack,只能等待超时重传了。而大文件有较大可能触发快速重传。
     
  • 相关阅读:
    C语言经典算法100例(二)
    Plus One @LeetCode
    hdu 4099 Revenge of Fibonacci 字典树+大数
    算法入门系列一--DP初步
    《当裸辞的程序猿遇上最冷季八》——第一次约女孩吃饭
    UVa 297
    手机NFC通信的安全车钥匙
    innosetup卸载软件后,删除定时任务schedule task
    VS2008调试程序时出现"XXX mutex not created."
    centOS7关闭防火墙的命令
  • 原文地址:https://www.cnblogs.com/Jummyer/p/11105981.html
Copyright © 2020-2023  润新知