ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 拥塞控制概述 * 拥塞控制是用来提高网络利用率,降低丢包率,并保证网络资源对每条数据流的公平性。 * 拥塞控制的四个部分:**慢启动**,**拥塞避免**、快速重传和快速恢复 * 拥塞控制算法在Linux下的实现有:reno算法、vegas算法和cubic算法 ## 最终控制变量 拥塞控制最终受控变量是向发送端向网络一次连续写入(收到其中第一个数据的确认之前)的数据量,我们称为SWND(send window,发送窗口)。不过,发送端最终以TCP报文段来发送数据,所以SWND限定来发送端能连续发送的TCP报文段数量。这些TCP报文段的最大长度(仅指数据 部分)称为SMSS(Sender Maximum Segment Size,发送着最大段大小),其值一般等于MSS。 * 发送端需要合理选择SWND大小,SWND太小,会引起网络延迟,反之如果SWND太大,则容易导致网络拥塞。 * 可以通过接收通告窗口(RWND)来控制发送端的SWND。 * RWND控制发送端的SWND显然不够,发送端引入了一个称为拥塞窗口(Congestion Window,CWND)的状态变量。实际的SWND值是RWND和CWND中的较小者。 ## 慢启动和拥塞避免 TCP建立好之后,CWND将被设置成初始值IW(Initial Window),其大小为2——4恶搞SMSS。 ### 什么是慢启动 发送端最多能发送IW字节的数据,此后发送端每收到接收端的一个确认,其CWND就按照如下方式增加: ``` CWND += min(N, SMSS); ``` 其中N是此次确认中包含的之前违背确认的字节数,这样一来,CWND将按照指数形式扩大,这就是所谓的慢启动。 >慢启动算法的理由是,TCP模块刚开始发送数据时并不知道网络的实际情况,需要用一种试探的方式平滑地增加CWND的大小。 ### 什么是拥塞避免 * 如果不施加其他手段,慢启动必然使得CWND很快膨胀(可见慢启动其实不慢)并最终导致网络拥塞。 * TCP拥塞控制中定义了另一个重要的状态变量:慢启动门限(slow start threshold size, ssthresh)。当CWND的大小超过该值时,TCP拥塞控制将进入拥塞避免阶段。 * 拥塞避免算法是的CWND按照线性方式增加,从而减缓其扩大。 * 每个RTT时间内按照`CWND += min(N, SMSS);`计算新的CWND,而不讨论该RTT时间内发送端接收到多少个确认。 * 每收到一个对新数据的确认报文段,就按照`CWND += SMSS*SMSS/CWND`来更新CWND ### 判断拥塞发生的依据 发送端判断拥塞发送的依据有两个 * 传输超时,或者说TCP重传定时器溢出 * 接收到重复的确认报文段。 对第一种使用慢启动和拥塞避免,对第二种情况则采用快速重传和快速恢复。 >第二种情况如果发生在重传定时器溢出之后,则也被拥塞控制当成第一种情况来对待。 如果发送端检测到拥塞发生是由于传输超时,即上述第一种情况,那么它将执行重传并做如下调整 `ssthresh=max(FlightSize/2, 2*SMSS) CWND<=SMSS`,其中FlightSIze是已经发送但未收到确认的字节数,这样调整之后,CWND将小雨SMSS,那么也必然小于新的慢启动门限值ssthresh。它一定不小于SMSS的2倍),故而拥塞控制再次进入慢启动阶段。 ## 快速重传和快速恢复 拥塞控制算法需要判断当收到重复的确认报文段时,网络是否真的发生来拥塞,活着说TCP报文段是否真的丢失了,具体做法是:发送端如果连续收到3个重复报文段,就认为是拥塞发生了。然后它启动快速重传和快速算法来处理拥塞。 * 当收到第三个重复的确认报文段时,按照`ssthresh=max(FlightSize/2, 2*SMSS) CWND<=SMSS`计算ssthresh,然后立即重传丢失的报文段,并按照`CWND=ssthresh+3*SMSS`设置CWND * 每次收到1一个重复的确认时,设置CWND=CWND+SMSS。此时发送端可以发送新的TCP报文段(如果新的CWND允许的话) * 当收到新数据的确认时,设置CWND=ssthresh(ssthresh是新的慢启动门限值,由第一步计算得到) 快速重传和快速恢复完成之后,拥塞控制将恢复到拥塞避免阶段,这一点由第三步操作可得知。