为什么要进行拥塞控制
因为网络中的数据包吞吐量有限,且级数过多,一旦数据包在某一跳被丢包,那么它之前所经过的所有路由器、交换机消耗的资源将变成无用功。
并且网络中的两个终端设备一般都有多条数据链路相连接而成,当一条链路通畅或拥塞时,需要有一种算法来帮助终端设备更好地利用现有的网络资源来达到资源最大化的效果。
TCP拥塞控制的参数定义
· 控制方式:端到端控制(没有网络辅助)
· 主体:发送方限制发送
LastByteSent-LastByteAcked < min( CongWin , RcvWindow )
· 在大体上,设备会限制自己发包的速度为:
rate = CongWin / RTT
(阻塞窗口除以往返时延)
CongWin
(cwnd) 是一个动态函数,用于感知网络拥塞。ssthresh
是一个阈值,用来划分TCP慢启动状态和拥塞避免状态,它也是一个动态的参数。MSS
(maximum segment size) 每一个报文段所能承载的最大数据长度,通常这个也是拥塞控制的最小单位。
TCP拥塞控制的三个阶段
慢启动
TCP连接初始化时,cwnd
默认为 一个MSS
。
当 cwnd
小于 ssthresh
时,每个RTT它都会加倍发包,以一个较快的速度达到 ssthresh
。
当 cwnd
大于等于 ssthresh
时,它将会转移到拥塞避免阶段。
拥塞避免
在这个状态中, 每个RTT它只会将发包的速度线性增加,即
cwnd = cwnd + MSS *(MSS/cwnd)
(when receiving a packet)。
(MSS/cwnd 为每个MSS包平均消耗的发包时间,这样的定义是为了让这个RTT里面发出的所有包得到回应时,cwnd能刚好增加一个MSS的大小)
快速恢复
前面的操作都没有提到快速恢复,这是因为前面两个状态随时都有可能转移到快速恢复上来,只需要满足一个条件: 收到同一个包三次。
这就表明了网络已经遭遇了拥塞,以至于同一个包被发送方发送了三次,终端必须改变它的参数来避免网络拥塞的状况,便会转移到快速恢复状态上来。
同时 ssthresh = cwnd / 2
, cwnd = ssthresh + 3
。
在这个状态中,每个RTT内终端都会检测自己是否能接收到数据包以及接收到的数据包的类型:
- 依然是重复发包:
cwnd = cwnd + MSS
。 - 收到了新的数据包:
cwnd = ssthresh
,并重置重复收包计数器,转至拥塞避免状态。 - 超时:不论什么情况下,超时都会导致状态直接转移回慢启动状态,并且所有参数重置,和刚刚建立TCP连接时的情况一样。