名词解释:
cwnd -- 拥塞窗口
ssthresh(slow start threshold)-- 慢启动到拥塞避免到阈值
RTT——Round Trip Time,也就是一个数据包从发出去到回来的时间
RTO(Retransmission TimeOut)重发超时时间
为什么有了滑动窗口还需要有拥塞窗口?
滑动窗口是对发送接收双方的流量控制,如果中间的网络设备的转发性能达到极限是无法感知到的,而tcp除了针对自身的收发能力做调整,还根据整体的网络情况做调整,所以有了拥塞窗口。
拥塞控制分为四个阶段,每个阶段的处理策略都不同,大概就是先猛增,然后小心增长预防拥塞,还有就是已经发生拥塞了的措施和快速恢复。
慢启动
此阶段的操作:
cwnd设置为一个很小的初始值,这个初始值在不同版本里面是不一样的,有1、3、10等。
每收到一个ack,cwnd = cwnd+1
cwnd*2
cwnd成指数级别递增。
跳出该阶段的标志:cwnd等于ssthresh时,进入拥塞避免阶段,那么ssthresh的值该设置成多少?将在后面介绍。
拥塞避免
此阶段的操作:
收到一个ACK时,cwnd = cwnd + 1/cwnd
当每过一个RTT时,cwnd = cwnd + 1
此阶段cwnd成线性增长。
跳出该阶段的标志:发生拥塞,此时进入发生拥塞阶段
发生拥塞
分为两种情况:
<!-- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px '.PingFang SC'} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px 'Helvetica Neue'} span.s1 {font: 12.0px 'Helvetica Neue'} -->
1)RTO超时,重传数据包。TCP认为这种情况网络上很糟糕了,反应也很强烈。
sshthresh = cwnd /2
cwnd 重置为初始值
进入慢启动过程
2)收到3个duplicate ACK,这种情况认为网络情况还可以,反应不是很强烈。
cwnd = cwnd /2
sshthresh = cwnd
进入快速恢复阶段
跳出该阶段的标志:出现一下,处理之后必然跳出到其他状态。
为什么快速恢复中会收到多个相同的ack,以及为什么认为收到多个相同ack要比RTO的网络情况好? 将在后面介绍。
快速恢复
cwnd = sshthresh + 3 * MSS (3的意思是确认有3个数据包被收到了)
重传Duplicated ACKs指定的数据包
如果再收到 duplicated Acks,那么cwnd = cwnd +1
如果收到了新的Ack,那么,cwnd = sshthresh ,然后就进入了拥塞避免的算法了
跳出该阶段的标志:出现一下,处理之后必然跳出到其他状态。
ssthresh的值该设置成多少?
动态的,因为不同设备,不同网络环境中网络等承载能力是不同的,初始值会设置很大, #define TCP_INFINITE_SSTHRESH 0x7fffffff,然后按照上面介绍的到了拥塞发生阶段,sshthresh会被设置成拥塞发生时候,拥塞窗口的一半。
为什么快速恢复中会收到多个相同的ack,以及为什么认为收到多个相同ack要比RTO的网络情况好?
这个是tcp的快速重传机制,接收方如果收到的包不连续,从断点开始,每次收到新包,都ack丢失点的序号,如果发送方连续收到3次相同的ack,就重传。Fast Retransmit的好处是不用等timeout了再重传。举例:如果发送方发出了1,2,3,4,5份数据,第一份先到送了,于是就ack回2,结果2因为某些原因没收到,3到达了,于是还是ack回2,后面的4和5都到了,但是还是ack回2,因为2还是没有收到,于是发送端收到了三个ack=2的确认,知道了2还没有到,于是就马上重转2。然后,接收端收到了2,此时因为3,4,5都收到了,于是ack回6。从上面也能看出收到三个相同的2的ack,起码说明网络中还能正常来回传输3,4,5等,说明网络还有的救,所以反应没那么激烈,而RTO说明这段时间不仅仅是2丢了,而且2丢了这段时间还没有收到后面的3个包,所以tcp就认为网络比较糟糕了,反应也比较激烈。