zoukankan      html  css  js  c++  java
  • TCP/IP学习笔记:TCP拥塞控制

    简介

    拥塞指的是

    在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏。这种情况就叫拥塞(congestion)。

    TCP模块任务:提供网络利用率,降低丢包率,保证网络资源对每条数据的公平性。---- 拥塞控制

    标准文档:RFC 5681,介绍了拥塞控制4个部分:慢启动(slow start)、拥塞避免(congestion avoidance)、快速重传(fast retransmit)和快恢复(fast recovery)。

    拥塞控制for linux算法实现,有多种:reno算法、vegas算法、cubic算法等。部分或全部实现。
    查看方式(for Ubuntu 14):

    $ cat /proc/sys/net/ipv4/tcp_congestion_control
    cubic
    

    我的PC是采用cubic算法。


    术语介绍

    拥塞控制最终受控变量:发送窗口(SWND,Send Window)。也就是说,拥塞控制算法最终是通过控制SWND大小,来进行拥塞控制的。

    发送窗口

    在发送端发送缓存,存在4种类型数据,其中,发送窗口SWND是指(2)和(3)

    (1)已经发送并且对端确认(Sent/ACKed)---------------发送窗外 缓冲区外
    (2)已经发送但未收到确认数据(Sent/UnACKed)----------发送窗内 缓冲区内
    (3)允许发送但尚未发送的数据(Unsent/Inside)---------发送窗内 缓冲区内
    (4)未发送暂不允许(Unsent/Outside)-----------------发送窗外 缓冲区内
    

    发送缓存4种类别数据的示意图

    接收窗口

    接收窗口 指的是TCP报文头窗口字段,用于告诉发送端自己当前接收缓存大小。

    发送者最大段大小 SMSS

    MSS(Maximum Segment Size) TCP最大报文段长度(RFC 879),指的是每一个TCP报文段中的数据字段的最大长度。

    TCP报文段 = 数据字段 + TCP首部(20~40Byte)
    MSS = MTU - sizeof(TCPHDR) + sizeof(IPHDR)
    

    MTU:最大传输单元(含TCP头部、IP头部);TCPHDR:TCP报文头;IPHDR:IP报文头。

    MSS与MTU含义见下图:

    发送者最大段大小,称为SMSS(Sender Maximum Segment Size)。

    如何通告MSS?
    MSS的默认值是536byte,因此对端应能接受报文段长度是536 + 20(TCP固定首部) = 556byte的TCP报文。如果想要改变MSS,就需要在TCP连接时,通过TCP报文头可变长的选项(option)字段(1byte类型+1byte长度+不定长内容),告知对端。
    注意:MSS是设置好值后,再通告对方,而非与对方协商。

    SWND大小的影响

    如果SWND太小,会引起明显的网络延迟;反之,如果SWND太大,则容易导致网络拥塞。

    既然接收窗口RWND可以控制发送窗口,为何还需要拥塞控制,而不直接用接收窗口进行控制?
    虽然接收方可以通过接收通告窗口(RWND),来控制发送端SWND。但是接收方并不知道网络拥塞情况,无法针对网络情况进行控制。因此,发送端引入了一个称为拥塞窗口的(Congestion Windo, CWND)的状态变量。实际的SWND值是RWND和CWND中较小者。


    慢启动和拥塞避免

    慢启动

    TCP连接建立OK后,CWND初值IW(Initial Window),大小2~4SMSS -- 发送端最多能发送IW bytes数据。
    此后,发送端每收到接收端的一个确认,其CWND就按下式增加:

    CWND += min(N, SMSS), 其中,N是此次确认中包含的之前未被确认的字节数   (1) 
    

    这样,CWND将按指数形式扩大,这就是慢启动。
    慢启动算法理由:TCP模块刚开始发送数据时,并不知道网络的实际情况,需要一种试探的方式平滑地增加CWND的大小。

    慢启动门限

    如果不施加其他手段,慢启动必然使得CWND很快膨胀(慢启动并不慢),并最终导致网络拥塞。而慢启动门限(slow start threadhold size, ssthresh),就是这样一个限制:

    当cwnd < ssthresh时,使用慢开始算法;
    当cwnd > ssthresh时,停止慢开始算法,改用拥塞避免算法;
    当cwnd = ssthresh时,既可以用慢开始算法,也可以用拥塞避免算法;
    

    ssthresh初始值16。只要判断出现拥塞时,慢开始门限设为出现拥塞时发送窗口swnd的一半(但不能<2),然后把拥塞窗口cwnd重新设为1,执行慢开始算法。
    目的:迅速减少主机发送到网络中的分组数,使得发生拥塞时路由器有足够时间把队列中积压的分组处理完毕。

    拥塞避免算法

    CWND按线性方式增加,从而减缓其扩大。RFC 5681提到2种实现方式:
    1)每个RTT时间内,按(1)式计算新的CWND,而不论该RTT时间内发送端收到多少个确认。
    2)每收到一对新数据的确认报文段,就按式(2)来更新CWND。

    CWND += SMSS * SMSS / CWND                                        (2)
    

    下图粗略地描述了慢启动和拥塞避免发生的时机和区别。此外,我们假设当前ssthresh = 16SMSS大小(实际远不止这么大)

    慢启动和拥塞避免,都是发送端在未检测到拥塞时,所采用的积极拥塞避免的方法。下面介绍拥塞发生时(可能发生在慢启动阶段或拥塞避免阶段)拥塞控制的行为。

    发送端如何判断拥塞发生?

    • 传输超时,或者说TCP重传定时器溢出; ---- 拥塞避免
    • 接收到连续3个重复的确认报文; ---- 快速重传,快速恢复

    拥塞控制对这两种情况有不同的处理方式。第一种情况,仍然使用慢启动和拥塞避免;第二种情况,则使用快速重传和快速回复(如果真的发生拥塞)。

    如果发送端检测到拥塞发生是由于传输超时,即上述第一种情况,那么它将执行重传并做如下调整:

    ssthresh = max(FlightSize / 2, 2 * SMSS)             (3)
    CWMD <= SMSS
    

    其中,FlightSize是已经发送但未收到确认的字节数。这样调整后,CWMD将小于SMSS,那么必然小于新的慢启动门限值ssthresh(根据式(3),ssthresh一定不小于SMSS的2倍),故而拥塞控制再次进入慢启动阶段。

    何为TCP超时重传?
    TCP服务必须能够重传超时时间内未收到确认TCP报文段。为此,TCP模块为每个TCP报文段都维护一个重传定时器,该定时器在TCP报文段第一次被发送时启动。如果超时时间内未收到对方的应答,TCP模块将重传TCP报文段并重置定时器。

    所谓超时,是指定时器 > 最大往返时间RTT。
    RTT是指一个数据报发送到目的地,然后到发送方收到确认所需的时间,这是测量RTT。发送报文和确认报文并非数量上的一一对应,可能发送多次,确认一次,也可能是一一对应。


    快速重传和快速恢复

    如何通过接收到重复的确认报文段,判断网络是否真的发生拥塞?
    发送端接收到重复的确认报文段可能情形:TCP报文段丢失,接收端收到乱序TCP报文段并重排等。

    拥塞控制算法需要判断当收到重复的确认报文段时,网络是否真的发生了拥塞,或者说TCP报文段是否真的丢失了。具体做法:
    发送端如果连续收到3个重复的确认报文段,就认为拥塞发生了。然后它启用快速重传和快速恢复算法来处理拥塞,过程如下:

    1)当收到第3个重复的确认报文段时,按(3)式计算ssthresh,然后立即重传丢失的报文,而不是等到重传计时器超时,这称为快速重传。并按式(4)设置CWND

    CWND = ssthresh + 3 * SMSS                             (4)
    

    2)每次收到1个重复的确认时,设置CWND = CWND + SMSS,而非从慢开始算法的cwnd=1开始。此时,发送端可以发生新的TCP报文段(如果新的CWND允许的话)

    3)当收到新数据的确认时,设置CWND = ssthresh(ssthresh是新的慢启动门限值,由第一步计算得到)

    步骤1)称为快速重传,步骤2)3)称为快速恢复。快速重传和快速恢复完成之后,拥塞控制将恢复到拥塞避免阶段。这点由第3)步操作可得知。


    总结

    拥塞控制对象:发送窗口SWND. SWND <= min(RWND, CWND)
    网络出现超时 => 采用慢开始算法 + 拥塞避免算法;
    网络出现重传 => 快速恢复算法;


    参考

    [1]谢希仁. 计算机网络.第5版[M]. 电子工业出版社, 2008.
    [2]游双. Linux高性能服务器编程[M]. 机械工业出版社, 2013.
    [3]Postel J . Transmission control protocol; rfc793[J]. Rfc, 1981.(RFC793)
    [4]Тезисы, Статусдокумента, Авторскиеправа, et al. RFC 5681 TCP Congestion Control. 1996.(RFC5681)

  • 相关阅读:
    索引
    静态成员实例
    异常实例
    继承实例
    构造函数实例
    verilog时序优化
    verilog语法笔记
    Idelay进行时序调节
    Vivado综合属性:ASYNC_REG
    verilog分频
  • 原文地址:https://www.cnblogs.com/fortunely/p/15042222.html
Copyright © 2011-2022 走看看