背景
TCP/IP
协议是当前网络时代的基础,所有的网络产品,或者是开发语言、开发框架都是基于tcp/ip
协议的,所以说,学好tcp/ip
对个人以后从事互联网行业会有巨大的帮助。
但是这是一个基础理论课程,就像操作系统这门课一样,学完之后可能不会对你产生太大的影响,不会让你立马拥有能够投入工作中的技能。但正是因为这是一个基础理论课,所有的互联网技术都是基于它的。所以如果你了解tcp/ip
协议,将会对你未来发展或者在工作中排查问题产生积极的作用。
tcp拥塞控制
上一篇说的流量控制发生在C和S之间,没有考虑到公网环境的影响,如果说当前公网质量特别差,很容易出现丢包,那么发送端就应该需要注意一些了。而这,也正是拥塞控制需要处理的问题。
拥塞窗口:防止发送方发的太快,使的网络来不及处理,从而导致网络拥塞!!
对于拥塞控制来说,tcp
每条连接都需要维护2
个核心状态:
- 拥塞窗口
- 慢启动阈值
其中涉及到的算法有以下几个:
- 慢启动
- 拥塞避免
- 快速重传
- 快速回复
接下来我们就来一一看看这些状态和算法。
状态
拥塞窗口(cwnd)
拥塞窗口是指自己还能传输的数据量大小。和接收窗口有些区别:
- 接收窗口(rwnd)是接收端给的限制
- 拥塞窗口(cwnd)是发送端自己的限制,默认为1个报文段
注意:
- 两者都相同之处,都是用来限制发送窗口的大小
发送窗口大小 = min(rwnd, cwnd)
。取两者最小值,而拥塞控制就是用来控制cwnd
的变化
慢启动阈值(ssthresh)
默认大小为65536byte
。当出现超时,阈值被设置为发送窗口的一般
,cwnd
设置为1
,然后重新启动慢启动算法!
算法
慢启动
刚开始传输数据的时候,你是不知道当前公网到底是稳定的还是拥堵的。如果做的太激进,发包太急,那么可能会出现疯狂丢包,造成雪崩式的网络灾难。同时也非常浪费公网资源。
因此,拥塞控制首先就是要采用一种保守的算法来慢慢地适应整个网络,这种算法就叫慢启动算法。过程如下:
- 首先,三次握手,双方宣告
rwnd
的大小 - 双方初始化自己的
cwnd
的大小 - 在开始传输的一段时间,发送端每收到一个
ACK
,cwnd
大小加1
。也就是说,每经过一个RTT
,cwnd
窗口大小翻倍。如果说初始窗口为10
,那么第一轮10
个报文传完且发送端接收到10
个ACK
确认后,cwnd
大小变为20
;第二轮变成40
;第三轮80
…
cwnd
大小不可能无限制增长下去,当cwnd
增长到阈值后(cwnd > ssthresh
),怎么来控制cwnd
窗口的大小呢?这就是拥塞避免需要做的事情了。
拥塞避免
原来每收到一个ACK
确认,cwnd
大小加1
。现在到达阈值后,cwnd
只能加一点点了:1/cwnd
。也就是说,以前一个RTT
下来,cwnd
大小翻倍。现在一个RTT
下来,cwnd
大小加1
拥塞避免示意图如下,其中采用AIMD
方法
AIMD
(加法增加,乘法减小)
- 乘法减小
无论在慢启动阶段还是在拥塞控制阶段,只要出现网络超时,就将ssthresh
设置为cwnd
的一半,然后将cwnd
置为1
个报文段。然后开始执行慢启动算法 - 加法增加
当网络频发超时情况时,ssthresh
会下降的很快,为来减少注入到网络中的分组数,加法增加是指执行拥塞避免后,将拥塞窗口缓慢增大,以防止网络中过早出现拥塞
注意:
- 慢启动阶段数据包发送量为指数级增长,拥塞避免阶段则为线性级增长
- 拥塞避免算法不能够完全避免网络拥塞,通过控制拥塞窗口的大小,只能是网络不易出现拥塞
快速重传
在tcp
传输的过程中如果发生来丢包,即接收端发现数据段不是按序到达的时候,接收端的处理方法是重复发送之前数据包的ACK
。比如,前4
个包已收到,第5
包丢了,即使此时第6、7
到达接收端,接收端也一律返回第4
个包的ACK
。当发送端收到>=3
个重复的ACK
时,意识到丢包了,于是马上进行重传,不用等到一个RTO
的时间到了才重传。
这就是快速重传,它解决的是是否需要重传的问题。
选择性重传
基于上面的情况,是重传第5
个包还是重传5、6、7
个包呢?
既然6、7
个包已经到达了,tcp
设计者也不傻,已经传过去了,干嘛还要传呢?干脆记录以下哪些包到达了,哪些包没到,针对性重传。
在收到发送端的报文后,接收端回复了一个ACK
报文,那么在该报文首部可选项中,就可以加上SACK
这个属性,通过left edge
和right edge
告知发送方已经收到了哪些区间的数据。因此,即使第5
个包丢了,当收到第6、7
个包后,接收端会告诉发送端,这两个包到了,剩下第5
个包没到,就重传这个包。
这个过程叫做选择性重传(SACK
),它解决的是如果重传的问题。
快速恢复
发送端收到了3
次重复的ACK
,发现丢包,觉得现在的网络已经有些拥塞了,自己会进入快速恢复阶段。如下:
ssthresh
值降低为cwnd
的一半cwnd
值等于ssthresh
cwnd
线性增加(加法增加)
总结
这是tcp/ip系列的第八篇,以上就是拥塞控制中的概念和算法。后面还有更深入、更多使用的场景讲解,这个系列的文章会很长。
开始下一篇吧。