一 什么是窗口以及窗口作用
1.1 什么是窗口
在TCP协议里,窗口是面向字节流的,一个窗口表示一定长度的字节数据, 窗口就可以用来收发一组连续的数据。TCP连接的两端都是可以收发数据的,收发两端都维护的有一个窗口结构。
1.2 窗口作用
#1 和停止等待协议使用,提升通信效率
#2 可以控制数据传输速率和流量
二 发送端和接收端窗口结构
2.1 发送端窗口
在发送缓冲区中,缓冲区分为4个部分:
提供窗口: 指的是已发送但是未确认+即将发送的窗口。这个窗口需要接收端确认之后才能确定。因为有可能存在丢包。
已发送并确认: 指的是这部分字节已经发送出去,并且接收端已经确认了,这部分缓存可以清理掉,重新使用
已发送未确认:指的是这部分字节已经发送出去,但是接收端还没有确认,这时候我们是不能滑动窗口,发送下一个窗口数据。因为没有确认,所以有可能出现丢失数据的情况
准备发送: 指的是如果已发送的窗口中的数据段全部确认了,就该接着发送的窗口
2.2 接收端窗口
已经接收并且确认: 指的是已经接受到了发送端的数据,并且确认了,就可以被应用程序读取。
已经接收,还没有确认:指的是已经接受到了发送端的数据,但是还没有确认
但凡超过了左右边界的都不会被接受,直接丢弃。因为要么重复了,要么就是发送了不该发送的数据。
三 什么是零窗口和TCP持续计数器
接收端的确认包中返回的window窗口大小为0,即使发送端有数据,这时候窗口也会缩减为0,停止发送数据
3.1 零窗口产生原因
为什么会有这种情况呢?接收端处理不过来了,缓存中如果已经放不下了,那就会给接收端确认包中的返回值为0
3.2 何时开始继续发送呢
当接收端重新获取可用空间的时候,会给发送端传输一个窗口更新,告诉发送端可用继续发送数据了,这样的窗口更新通常是没有数据的,只是首部更新
3.3 如果这个窗口更新数据包丢失了,怎么办?
如果这个窗口更新数据包丢失了,那么通信双方就会处于互相等待的状态,接收方等待接收数据,发送方等待接收方窗口更新数据。为了防止这种死锁的产生,发送端会采用一个持续计时器间歇性的查询接收端,强制要求接收端返回窗口大小。当TCP计时器超时的时候就会触发这个窗口探测请求。
四 滑动窗口的工作流程
4.1 正常情况
#1 将窗口内的数据段发送出去
#2 接收端开始接收每一个段的数据,然后放入接收窗口中
#3 接收完毕之后,给发送端返回确认包,确认包包含下一次应该从哪个字节开始发送和窗口大小(从哪儿发,发多少)
#4 确认之后,窗口后移,然后确认的数据就可以被应用程序读取
#5 发送端收到确认后,窗口根据确认包window大小向后滑动
#6 发送端确认的缓存可以清理,重复使用了
4.2 如果遇到数据段丢失的情况
#1 将窗口内的数据段发送出去
#2 如果一个数据段在发送的途中丢掉了
#3 接收端在接收的时候,如果遇到数据包丢失的数据段,则向发送端返回的确认包的确认号为丢失数据段的开始字节序列
#4 发送端收到接收端的确认后,根据确认信息,看接收端确认了几个连续数据段,然后将窗口向后移动几个
#5 因为此时丢失的段可能还没有到达超时时间,所以先将新加入窗口的数据段先发送出去,然后等待丢失数据段超时再重新发送。(注意这里丢失数据段后面非新加入窗扣的数据段是否也需要重传取决于使用的何种重传策略,一般都是SACK,这样的话后面如果已经确认过,就没有必要重传)