TCP流量控制
TCP滑动窗口
TCP的滑动窗口机制是用于控制数据传输流量和保证数据可靠性的重要机制。它通过动态调整窗口大小,来管理发送方和接收方之间的数据传输。
首先,在 TCP 的发送方和接收方各有一个窗口。并且因为 TCP 是一个全双工通信的协议,所以大多数时候,客户端和服务端都是既有接收窗口,又有发送窗口。
发送窗口
整体分为三个部分:

- 在整个窗口左边的,就是已经发送并且 ACK 的报文。比如说上图中编号小于 100 的报文;
- 滑动窗口内的报文,又可以分成三部分:
- 已经收到 ACK 的报文,例如说 101 和 102;
- 已经发送但是没收到 ACK 的报文,比如说 100, 103 和 104;
- 还没发送的报文,也就是 105,106 和 107;
- 在整个窗口右边的,窗口还没滑过去,所以暂时它们不可能被发送,在上图是编号大于 107 的报文;
进一步看,这里有一个细节,就是虽然 100 编号比较小,但是它的 ACK 反而有可能比 101 和 102 后收到。假设说现在收到了 100 的 ACK,那么这时候窗口就要开始滑动了。滑动的距离就是从窗口的左边开始出发,直到遇到第一个还没收到 ACK 的报文,在这里就是 103。

接受窗口
而接收窗口,也是类似的:

可以看到,在接收窗口也遇到不连续的问题,比如说先收到了 104。
显然,一旦接收方收到了 100 之后,它的窗口也会开始移动,移动的逻辑是类似的,找到最小的没有收到的报文。如下图。但是要注意到,因为 100 之后的 101 和 102 都收到了,所以实际上它可以直接 ACK 102。

因此你基本上可以想到整个工作流程:
- 初始化:连接建立时,双方协商初始窗口大小。协商是发生在 TCP 三次握手的第一次握手中。
- 发送数据:发送方根据窗口大小发送数据包,并等待接收方的确认。
- 接收确认:接收方收到数据包后,发送ACK确认,并更新接收窗口。
- 滑动窗口:发送方收到ACK后,滑动窗口向前移动,允许发送新的数据包。
- 动态调整:根据网络状况和接收方的处理能力,窗口大小可以动态调整。
动态调整窗口(最难)
这里的难点就是动态调整的策略。
就接收方来说,它主要是考虑自己的缓冲区。如果要是还有很多空闲缓冲区,那么接收方就可以增大自己的窗口,并且在发给发送方的报文里面带上新的窗口大小。反之则是减小窗口。最极端的情况下,接收方会返回零缓冲区,也就是提醒发送方不要再发了,自己已经没有空闲缓冲区可用了。
而发送方主要是受到两方面的影响。
一方面是受到 TCP 协议内部的慢开始、拥塞避免、快开始、快重传和快恢复策略的影响。另外一方面则是还会受到接收方窗口大小的影响。