tcp协议 拥塞控制

补充tcp协议与滑动窗口
咱们在向对端发送数据时,并非一股脑子任意发送,由于TCP创建链接后,就是创建了一根管道,这跟管道上,实际上有不少的工做设备,好比路由器和交换机等等,他们都会对接收到的TCP包进行缓存,以便实现排序,而后发送,可是这些设备并非只为一个TCP链接中转数据包,大量的网络包也许会耗尽存储空间,从而致使TCP链接的吞吐量急剧降低。为了不这种状况的发送,TCP的设计必须是一种无私的协议,它必须去探测这种网络拥塞的问题,不然咱们想一想,一旦出现拥塞(判断是否丢包或者是否发生重传),若是TCP只能作重传,那么重传数据包会使得网络上的包更多,网络的负担更重,因而致使更大的延迟以及丢更多的包,因而会进入一个恶性循环,若是网络上的全部TCP链接都是如此行事的话,那么立刻就会造成“网络风暴”,会拖垮整个网络,这也是一个灾难。那么TCP就应该可以检测出来这种情况,当拥塞出现时,要作自我牺牲,就像交通阻塞同样,每一辆车都应该把路给让出来,而不是再去抢路了。这说的就是拥塞控制。那是如何控制的呢?算法

首先,咱们得看TCP是如何充分利用网络的,TCP实际上就是逐步探测这个通道的传输的最大能力,这个逐步探索就是咱们要讲的慢启动算法,这个慢启动算法就是:新创建的链接不能一开始就大量发送数据包,而是应该根据网络情况,逐步地增长每次发送数据包的量。segmentfault

具体的工做步骤就是:缓存

  • 慢启动算法:网络

    • 发送方维护一个拥塞窗口,刚开始时,这个拥塞窗口(cwnd,congestion window)设置为1,这个1表明是一个MSS个字节。
    • 若是每收到一个ACK,那么就指数增加这个cwnd(2,4,8,16,32,64)等,
    • 实际上不会这么一直指数级增加下去,TCP会设置一个慢启动的阈值(ssthresh,slow start threshold,65535个字节) ,当cwnd >= ssthresh时,进入拥塞避免阶段。
  • 拥塞避免阶段ssh

    • 每收到一个ACK时,cwnd = cwnd + 1/cwnd;
    • 每当每过一个RTT时,cwnd = cwnd + 1;

这样放缓了拥塞窗口的增加速率,避免增加过快致使网络拥塞,慢慢的增长调整到网络的最佳值。在这个过程当中若是出现了拥塞,则进入拥塞状态。
拥塞状态 那是如何判断出现拥塞状态呢?只要出现丢包就认为进入了拥塞状态。进入拥塞状态也分两种状况:
1) 等到RTO超时(重传超时),重传数据包。TCP认为这种状况太糟糕,反应也很强烈:tcp

  • sshthresh = cwnd /2
  • cwnd 重置为 1
  • 进入慢启动过程

快速重传
2)连续收到3个duplicate ACK时,重传数据包,无须等待RTO。此状况即为下面的快速重传。网站

【问题】什么状况下会出现3个duplicate ACK?设计

TCP在收到一个乱序的报文段时,会当即发送一个重复的ACK,而且此ACK不可被延迟。排序

若是连续收到3个或3个以上重复的ACK,TCP会断定此报文段丢失,须要从新传递,而无需等待RTO。这就叫作快速重传。路由

TCP Tahoe的实现和RTO超时同样。 TCP Reno的实现是:

  • sshthresh = cwnd
  • cwnd = cwnd /2
  • 进入快速恢复算法——Fast Recovery

上面咱们能够看到RTO超时后,sshthresh会变成cwnd的一半,这意味着,若是cwnd<=sshthresh时出现的丢包,那么TCP的sshthresh就会减了一半,而后等cwnd又很快地以指数级增涨爬到这个地方时,就会成慢慢的线性增涨。咱们能够看到,TCP是怎么经过这种强烈地震荡快速而当心得找到网站流量的平衡点的。

快速恢复算法

  • TCP Reno

这个算法定义在RFC5681。快速重传和快速恢复算法通常同时使用。快速恢复算法是认为,你还有3个Duplicated Acks说明网络也不那么糟糕,因此没有必要像RTO超时那么强烈。 注意,正如前面所说,进入Fast Recovery以前,cwnd 和 sshthresh已被更新:

  • sshthresh = cwnd
  • cwnd = cwnd /2

而后,真正的Fast Recovery算法以下:

  • cwnd = sshthresh + 3 * MSS (3的意思是确认有3个数据包被收到了)
  • 重传Duplicated ACKs指定的数据包
  • 若是再收到 duplicated Acks,那么cwnd = cwnd +1
  • 若是收到了新的Ack,那么,cwnd = sshthresh ,表明恢复过程结束,而后就进入了拥塞避免的算法了。

若是咱们仔细思考一下上面的这个算法,你就会知道,上面这个算法也有问题,那就是——它依赖于3个重复的Acks。注意,3个重复的Acks并不表明只丢了一个数据包,颇有多是丢了好多包。但这个算法只会重传一个,而剩下的那些包只能等到RTO超时,因而,进入了恶梦模式——超时一个窗口就减半一下,多个超时会超成TCP的传输速度呈级数降低,并且也不会触发Fast Recovery算法了。

  • TCP New Reno

因而,1995年,TCP New Reno(参见 RFC 6582 )算法提出来:

  • 当sender这边收到了3个Duplicated Acks,进入Fast Retransimit模式,开发重传重复Acks指示的那个包。若是只有这一个包丢了,那么,重传这个包后回来的Ack会把整个已经被sender传输出去的数据ack回来。若是没有的话,说明有多个包丢了。咱们叫这个ACK为Partial ACK。
  • 一旦Sender这边发现了Partial ACK出现,那么,sender就能够推理出来有多个包被丢了,因而乎继续重传sliding window里未被ack的第一个包。直到再也收不到了Partial Ack,才真正结束Fast Recovery这个过程。

咱们能够看到,这个“Fast Recovery的变动”是一个很是激进的玩法,他同时延长了Fast Retransmit和Fast Recovery的过程。

相关文章
相关标签/搜索