本篇中先介绍一下慢启动和拥塞避免的大概过程,下一篇中将会给出多个linux下reno拥塞控制算法的wireshark示例,并详细解释慢启动和拥塞避免的过程。

一、慢启动(slow start)

一个TCP连接启动的时候并不知道cwnd应该取多大的值适合当前的网络状况,因此TCP发送方会从一个较小的初始值指数抬升cwnd到某一个值,这个cwnd抬升的过程就叫做慢启动。除了初始建立tcp连接(SYN包交换后)后的数据发送使用慢启动外,在TCP超时重传、TCP空闲一段时间后重新开始数据发送这些场景下也会触发慢启动过程。

在TCP连接的慢启动过程中,cwnd的初始值为IW(initial window)。IW的原始值为1个SMSS的大小,但是RCF5681协议允许IW按照如下设置(RFC3390中也有详细的设置原则描述和讨论)

  • SMSS>2190bytes时,IW=2*SMSS 且最大不能超过2个报文段

  • 2190bytes>=SMSS>1095bytes时,IW=3*SMSS 且最大不能超过3个报文段

  • 其他场景下,IW=4*SMSS 且最大不能超过4个报文段

为了接下来描述方便,我们取cwnd=IW=1*SMSS。其中SMSS一般为min(接收方的MSS,扣除header的path MTU)。假设没有丢包发生并且接收方每接收一个包就反馈一个ACK,则每当发送方接收到一个Good ACK的时候,发送方就会调整cwnd=cwnd+min(N,SMSS),其中N表示这个Good ACK反馈确认的接收方新收到的数据量,单位为byte。比如之前收到的最大ACK Number为1000,新收到的Good ACK中ACK Number为2000,则这个Good ACK指示接收方新收到了1000byte的数据,这种场景下N=1000bytes。当发送端以SMSS大小发送数据报文,接收方对每个报文都立即回复ACK的时候,简洁的整理以下算法流程如下

1)连接建好的开始先初始化cwnd = 1,表明可以传一个SMSS大小的数据。

2)每当收到一个ACK,cwnd++; 呈线性上升

3)每当过了一个RTT,cwnd = cwnd*2; 呈指数让升

4)还有一个慢启动门限ssthresh(slow start threshold),是一个上限,当cwnd >= ssthresh时,就会进入拥塞避免。

5)当遇到RTO超时重传时会触发cwnd和ssthresh的调整,ssthresh=max(cwnd/2, 2),cwnd=1,然后重新开始慢启动过程。

连接初始建立场景下可以设置ssthresh为一个很大的值,然后开始慢启动流程后,直到发送速率一直增大,最终触发RTO超时或者快速重传,然后根据cwnd设置ssthresh从而得到一个有效的ssthresh值。这里我们暂时只考虑RTO超时场景,后面会介绍快速重传、ECN等场景下的处理。

慢启动流程示意图如下

从上图可以看到每过一个RTT,cwnd就会增加一倍,因此TCP的慢启动是指数增长的(慢启动的"慢"是指TCP的发送端不能直接以接收方通告的awnd为窗口进行发送,而要有一个启动过程,因此叫做慢启动)。当发送端使用delay ACK时,慢启动的cwnd仍然是指数增长的,但是增长速度会稍微慢一些。因此有一些TCP实现会等TCP连接完成慢启动过程后在使用delay ACK,例如linux中在连接初始建立时候的quick ACK模式。

二、拥塞避免(congestion avoidance)

从慢启动可以看到,cwnd可以很快的增长上来,从而最大程度利用网络带宽资源,但是cwnd不能一直这样无限增长下去,一定需要某个限制。TCP使 用了一个叫慢启动门限(ssthresh)的变量,当cwnd超过该值后,慢启动过程结束,进入拥塞避免阶段。慢启动门限 ssthresh 的用法如下:

  • 当 cwnd < ssthresh 时,使用慢开始算法。

  • 当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。

  • 当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞避免算法。

拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢地增大,假设cwnd=k*SMSS,当发送端收到一个包的ACK反馈的时候,按照cwnd=cwnd+(1/k)*SMSS。这样每经过一个RTT发送k个数据包的时候,cwnd增长了大约一个SMSS,通常上我们即描述为每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1,使拥塞窗口 cwnd 按接近线性规律缓慢增长。这种增长方式叫做“加法增大”(Additive Increase)。另外当接收方使用delay ACK时,cwnd的增长仍然是接近线性的,只不过增长速度相对慢一些。总结如下

  1)收到一个ACK时,cwnd = cwnd + 1/cwnd

  2)当每过一个RTT时,cwnd = cwnd + 1

简单图示如下

无论在慢开始阶段还是在拥塞避免阶段,在Tahoe版本中,只要发送方判断网络出现拥塞(其根据就是触发了快速重传或者RTO重传),就要更新慢开始门限 ssthresh =max(flight size/2,2*SMSS),因为一般情况下flight size接近或者等于cwnd,所以也可以认为更新ssthresh =max(cwnd/2,2*SMSS),这个过程叫做“乘法减小”(Multiplicative Decrease)。加法增大与乘法减小常常合称为AIMD算法。另外,Windows中的实现据传为ssthresh =max(min(cwnd, awnd)/2, 2*SMSS) 。总结如下

  • sshthresh = max(cwnd/2,2*SMSS)  (一般来说当发生丢包的时候 cwnd一般都是大于等于4的,所以也可以认为ssthresh =max(cwnd/2,2*SMSS)=cwnd/2)
  • cwnd 重置为 1
  • 进入慢启动过程

三、拥塞控制示例

上面所讲解的慢启动和拥塞避免就是Tahoe版本的TCP实现,这个也是带有拥塞控制功能的第一个TCP版本,随着4.2 BSD UNIX一起发布。同时Tahoe版本是支持快速重传的,但是Tahoe版本对于快速重传和RTO重传的处理是一致(Reno版本的TCP对于快速重传和RTO重传的处理略有不同,接下来的拥塞控制系列会讲解)。

下面我们看一个图解示例以加深理解,下图中横坐标以RTT为单位,纵坐标cwnd用报文段为单位(可以看成SMSS大小为单位),我们假设接收端通告的窗口足够大,只考虑cwnd的变化。

分别对图中标示的箭头做如下说明

1、在标号为1的箭头处,TCP初始连接进行数据交换,开始慢启动,初始cwnd=IW=1,ssthresh=16,在传输轮次0-4阶段进行慢启动过程,cwnd按照1-2-4-8-16的顺序进行指数增长

2、在标号为2的箭头处,cwnd=16=ssthresh,此时触发拥塞避免过程,开始线性增长,在传输轮次4-12阶段,cwnd按照16-17-18-19-20-21-22-23-24进行线性增长。

3、在标号为3的箭头处,TCP发生了RTO重传,认为网络发生拥塞,于是设置ssthresh=cwnd/2=12,cwnd=1重新进行慢启动过程

4、在标号为4的箭头处,TCP从cwnd=1开始重新开始慢启动过程

5、在标号为5的箭头处,当 cwnd = 12 时改为执行拥塞避免算法,拥塞窗口按按线性规律增长,每经过一个往返时延就增加一个 MSS 的大小。

附件列表

TCP系列40—拥塞控制—3、慢启动和拥塞避免概述的更多相关文章

  1. TCP系列41—拥塞控制—4、Linux中的慢启动和拥塞避免(一)

    一.Linux中的慢启动和拥塞避免 Linux中采用了Google论文的建议把IW初始化成了10了.在linux中一般有三种场景会触发慢启动过程 1.连接初始建立发送数据的时候,此时cwnd初始化为1 ...

  2. TCP系列54—拥塞控制—17、AQM及ECN

    一.概述 ECN的相关内容是在RFC3168中定义的,这里我简单描述一下RFC3168涉及的主要内容. 1.AQM和RED 目前TCP中多数的拥塞控制算法都是通过缓慢增加拥塞窗口直到检测到丢包来进行慢 ...

  3. TCP系列44—拥塞控制—7、SACK关闭的快速恢复

    ) return;    delta = ssthresh - in_flight;     prr_delivered += newly_acked_sacked; if (delta < 0 ...

  4. TCP系列43—拥塞控制—6、Congestion Window Validation(CWV)

    一.概述 在RFC2861中,区分了TCP连接数据传输的三种状态   After sending a data segment:       If tcpnow - T_last >= RTO ...

  5. TCP系列39—拥塞控制—2、拥塞相关算法及基础知识

    一.拥塞控制的相关算法 早期的TCP协议只有基于窗口的流控(flow control)机制而没有拥塞控制机制,因而易导致网络拥塞.1988年Jacobson针对TCP在网络拥塞控制方面的不足,提出了& ...

  6. TCP系列55—拥塞控制—18、其他拥塞控制算法及相关内容概述

    前面我们演示分析了100+个wireshark TCP实例,拥塞控制部分也介绍常见的拥塞处理场景以及4种拥塞撤销机制,但是我们一直使用的都是reno拥塞控制算法.实际上拥塞控制发展到今天已经有了各种各 ...

  7. TCP系列42—拥塞控制—5、Linux中的慢启动和拥塞避免(二)

    在本篇中我们继续上一篇文章wireshark的示例讲解,上一篇介绍了一个综合示例后,本篇介绍一些简单的示例,在读本篇前建议先把上一篇读完,为了节省篇幅,本篇只针对一些特殊的场景点报文进行讲解,不会像上 ...

  8. TCP系列51—拥塞控制—14、TLP、ER与拥塞控制

    一.概述 这里的重点是介绍TLP.ER与拥塞控制并不是介绍TLP和ER本身,因此TLP和ER的详细内容请翻前文. 在TLP与拥塞控制的交互中有几个点需要注意 1.TLP触发的重传后,TCP仍然处于Op ...

  9. TCP系列48—拥塞控制—11、FRTO拥塞撤销

    一.概述 FRTO虚假超时重传检测我们之前重传章节的文章已经介绍过了,这里不再重复介绍,针对后面的示例在说明两点 1.FRTO只能用于虚假超时重传的探测,不能用于虚假快速重传的探测. 2.延迟ER重传 ...

随机推荐

  1. 使用百度编辑器--ueditor,后台接收提交编辑的内容,HTML不见了, 赋值不了,赋值之后,html暴露出来了??

    1.提交编辑好的内容, 后台post 接收发现 html 不见了,这个时候也许就是转义的问题, 既可以试试 $content = htmlspecialchars(stripslashes(input ...

  2. 【Android】添加依赖包

    貌似好像不知一种方法,以后有时间再研究,下面是其中的一种方法

  3. 【C】switch-case里面,加或不加break的区别

    int test; test = ; switch(test) { : test++; printf("value = 0"); // 打印printf,后续没有break代码,系 ...

  4. PHP array_reduce()函数的应用解析

    实例 向用户自定义函数发送数组中的值,并返回一个字符串: <?php function myfunction($v1,$v2) { return $v1 . "-" . $v ...

  5. 使用OpenLayers发布地图

    OpenLayers是用于制作交互式Web地图的开源客户端JavaScript类库,制作的地图几乎可以在所有的浏览器中查看.因为是客户端类库,它不需要特殊的服务器端软件或配置,甚至不用下载任何东西就可 ...

  6. 1030: [JSOI2007]文本生成器

    1030: [JSOI2007]文本生成器 https://www.lydsy.com/JudgeOnline/problem.php?id=1030 分析: AC自动机+dp. 正难则反,求满足的, ...

  7. Qt官方开发环境生成的exe发布方式

    本来想自己写一个打包程序的文章了,但是我发现了宝贝,在这里,大神写的比我牛逼的多了,这里做一下搬运工 一是为了方便大家 二是为了以后方便自己找 原文链接:http://tieba.baidu.com/ ...

  8. centos7下搭建django

    安装环境:centos7.4 1 安装nginx yum install nginx 注:尝试过在本地和腾讯云上安装,使用同一条命令:在本地安装提示没有可用安装包,云上安装正常 启动nginx,并启用 ...

  9. 基于Python的接口自动化

    第一步 Python的安装配置 打开官网: https://www.python.org/downloads/ 目前官网上已经更新到3.6.1啦,有两个版本,大家可以按自己喜欢的去下载,我自己选择的是 ...

  10. Android Studio|IntelliJ IDEA 常用快捷键(Mac|Window)

    一 For Mac(Mac OS X 10.5+) F1 显示注释文档F2 高亮错误或警告快速定位Command + F12 显示当前文件的结构(查看所有方法)Command + F 查找文本Comm ...