流量控制的意义
TCP提供了流量控制功能,流量控制就是发送窗口要根据接收窗口的实际情况来控制发送数据包的速度。
为什么要控制流量呢?
因为如果不考虑接收窗口的接收能力,发送窗口以超出接收窗口的能力来发送数据包,接收窗口没有能力接收,只能造成数据包的丢失,然后造成发送方的重传,不仅浪费了网络资源,还会加重网络的拥堵。
流量控制
正常情况下,发送窗口和接收窗口的大小基本是相等的。
我们考虑这种情况:
1、接收方应用由于应用程序个人原因导致读取数据变慢甚至停止
一开始的时候,发送窗口和接收窗口的大小是基本一致的。
当接收窗口在接收到数据后,就会发送对应的ack包,而发送端口一旦接收到对应的ack包,就会将发送端口右移,从而发送新的数据。发送窗口的大小不变。
但是应用程序如果读取变慢,这个时候接收窗口的右边界就无法右移来接收更多的数据包,这就会导致接收窗口慢慢变小甚至可能为0。
这时发送端口的大小和接收端口的大小是不匹配的,为了达到收发平衡,这种情况下TCP会降低发送方的发送窗口大小,达到接收之间的平衡,这就是流量控制!
TCP通过ack报文携带接口窗口大小信息来保证流量控制!
当接收窗口减小的时候,在返回ack包的时候,会携带接收窗口的大小信息返回给发送窗口,发送窗口也会根据接收窗口的大小来缩小自己的发送窗口,减少发送的速率。
接收窗口为0的特殊情况
接收窗口是可能为0的,这时如果发送端口收到接收窗口为0的消息会怎么 做呢?
发送窗口会停止发送数据,接收方应用程序读取数据后,接收窗口非0的时候,会给发送窗口发送一个ack报文,将发送窗口唤醒。
心细的你可能会说,如果这个唤醒ack报文丢失了呢?那么双方不就会陷入死锁状态,互相等待吗
针对这个问题,TCP采取了这种做法:
当发送窗口接收到了接收窗口为0的ack报文后,会启动一个计时器,当计时器超时后,会发送一个窗口探测报文。接收方接收到窗口探测报文后,会返回一个ack报文,ack报文中记录着接收窗口大小信息。
**1、**如果接收窗口大小仍为0,就会重新计时。
**2、**如果接收窗口大小大于0,发送窗口就会调整发送窗口大小,然后恢复发送数据。
如果窗口探测报文也丢失了呢?
如果窗口探测报文丢失了,或者对应的ack报文丢失了, 发送方会每隔一段时间发送一个窗口探测报文,如果超过3次都收不到对应的ack报文,就会中断连接。