tcp 为了防止发送方无脑的发送数据,导致接收方缓冲区被填满,所以就有了滑动窗口的机制,它可利用接收方的接收窗口来控制发送方要发送的数据量,也就是tcp流量控制。
如果一直无脑的发数据给对方,但对方处理不过来,那么就会导致触发重发机制,从而导致网络流量的无端的浪费。
为了解决这种现象发生,tcp 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。
下面举个栗子,为了简单起见,假设以下场景:
客户端是接收方,服务端是发送方
假设接收窗口和发送窗口相同,都为 200
假设两个设备在整个传输过程中都保持相同的窗口大小,不受外界影响
根据上图的流量控制,说明下每个过程:
- 客户端向服务端发送请求数据报文。这里要说明下,本次例子是把服务端作为发送方,所以没有画出服务端的接收窗口。
- 服务端收到请求报文后,发送确认报文和 80 字节的数据,于是可用窗口 usable减少为 120 字节,同时 snd.nxt 指针也向右偏移 80 字节后,指向 321,这意味着下次发送数据的时候,序列号是 321。
- 客户端收到 80 字节数据后,于是接收窗口往右移动 80 字节,rcv.nxt 也就指向 321,这意味着客户端期望的下一个报文的序列号是 321,接着发送确认报文给服务端。
- 服务端再次发送了 120 字节数据,于是可用窗口耗尽为 0,服务端无法在继续发送数据。
- 客户端收到 120 字节的数据后,于是接收窗口往右移动 120 字节,rcv.nxt 也就指向 441,接着发送确认报文给服务端。
- 服务端收到对 80 字节数据的确认报文后,snd.una 指针往右偏移后指向 321,于是可用窗口 usable 增大到 80。
- 服务端收到对 120 字节数据的确认报文后,snd.una 指针往右偏移后指向 441,于是可用窗口 usable 增大到 200。
- 服务端可以继续发送了,于是发送了 160 字节的数据后,snd.nxt 指向 601,于是可用窗口 usable 减少到 40。
- 客户端收到 160 字节后,接收窗口往右移动了 160 字节,rcv.nxt 也就是指向了 601,接着发送确认报文给服务端。
- 服务端收到对 160 字节数据的确认报文后,发送窗口往右移动了 160 字节,于是snd.una 指针偏移了 160 后指向 601,可用窗口 usable 也就增大至了 200。