TCP必须使用端到端拥塞控制而不是使网络辅助的拥塞控制,因为IP层不向端系统提供显式的网络拥塞反馈。TCP采用的方法是让每一个发送方根据所感知到的网络拥塞程度来限制其能向连接发送流量的速率。
TCP限制向其连接发送流量
TCP连接的每一端都是由一个接收缓存、一个发送缓存和几个变量组成。运行在发送方的TCP拥塞控制机制跟踪一个额外的变量,拥塞窗口(cwnd),它对一个TCP发送方能向网络中发送流量的速率进行了限制:在一个发送方中未被确认的数据量不会超过cwnd和rwnd中的最小值,即 LastByteSent - LastByteAcked <= min{cwnd, rwnd}.
通过约束发送方中未被确认的数据量,间接限制了发送方的发送速率。考虑一个丢包和发送时延均可以忽略不计的连接。在每个往返时间 (RTT)的起始点,上面的限制条件允许发送方向该连接发送cwnd个字节的数据,在该RTT结束时发送方接收对数据的确认报文。因此,该发送方的发送速率大概为 cwnd/RTT 字节/秒。
TCP检测网络发生拥塞
当出现超时未反馈或者收到接收方的3个冗余ACK,则出现丢包事件。则发送方认为在发送方到接收方的路径上出现了拥塞的指示。
冗余ACK是指接收方回给发送方和之前的ACK相同的一个ACK。这出现在,当接收方本应该接收X字节开头的报文,却收到X字节之后的某字节开头的报文(即X字节开始的报文丢失)时,接收方返回给发送方和上次相同的ACK报文,即报文的确认号位置仍然填写X。
这样发送方就知道X字节开始的报文丢失,从而会重传X字节开头的报文。
TCP拥塞控制算法
TCP拥塞控制算法包括慢启动、拥塞避免、快速恢复三个部分。
1. 慢启动
TCP连接开始时,cwnd的值通常初始置为一个MSS的较小值,这就使得初始发送速率大约为 MSS/RTT;之后,每收到一个报文段的首次被确认cwnd就增加一个MSS。这样,第一个RTT中,cwnd为1 MSS, 第二个RTT中,cwnd为2 MSS, 第三个RTT中,cwnd为4 MSS, 即每个RTT之后,cwnd就翻倍,cwnd呈指数增长。
当发生丢包时,设置一个变量 ssthresh(慢启动阈值) = cwnd / 2, 然后cwnd重新设为1。
2. 拥塞避免
当出现丢包时,如果(可能会直接进入快速恢复)进入慢启动阶段,ssthresh设为 cwnd/2, cwnd值置为1,然后每个RTT cwnd翻倍,当cwnd值到达 ssthresh之后,进入拥塞避免阶段。
此时,每个RTT,cwnd值只增加1个MSS,即每收到一个报文的ACK,cwnd = cwnd + MSS/cwnd.直到再次出现丢包后。当出现超时类型的丢包时,进入慢启动阶段(ssthresh = cwnd/2, cwnd=1);当出现三次冗余ACK类型的丢包时,进入快速恢复阶段(ssthresh = cwnd/2, cwnd = ssthreash + 3MSS)
3. 快速恢复
当出现三次冗余ACK类型的丢包时,进入快速恢复阶段。此时 ssthresh = cwnd/2, cwnd = ssthreash + 3MSS,之后每个RTT内,cwnd增加1个MSS,直到出现丢包。