今天我们来看TCP的滑动窗口问题,无论是在工作中,还是在笔试面试中,滑动窗口都是非常重要的概念,今天,图文并茂给大家讲清楚,一起来看看。
一、TCP的优势
TCP经过多年厮杀,早已确立了坚实的江湖基础,是**面向连接,可靠,基于字节流的传输层协议。**所谓可靠,就是确保数据准确的,不重复,无延迟的到达目的地;
TCP的总结如下:
①数据分片:在发送端对用户数据进行分片,在接收端进行重组,由TCP确定分片的大小并控制分片和重组;
②到达确认:接收端接收到分片数据时,根据分片数据序号向发送端发送一个确认;
③超时重发:发送方在发送分片时启动超时定时器,如果在定时器超时之后没有收到相应的确认,重发分片;
④滑动窗口:TCP连接每一方的接收缓冲空间大小都固定,接收端只允许另一端发送接收端缓冲区所能接纳的数据,TCP在滑动窗口的基础上提供流量控制,防止较快主机致使较慢主机的缓冲区溢出;
⑤失序处理:作为IP数据报来传输的TCP分片到达时可能会失序,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层;
⑥重复处理:作为IP数据报来传输的TCP分片会发生重复,TCP的接收端必须丢弃重复的数据;
⑦数据校验:TCP将保持它首部和数据的检验和,这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到分片的检验和有差错,TCP将丢弃这个分片,并不确认收到此报文段导致对端超时并重发。
其中很重要的一环就是“滑动窗口”,下面我们重点关注一下。
二、滑动窗口的引入
IP 层协议属于不可靠的协议,IP 层并不关系数据是否发送到了对端,在复杂的网络中,由于各种各样的原因,接收到数据包的顺序不一定和发送的顺序相同,这就是乱序问题。这种情况下,有必要为每个包定义一个序号seq,每个包用一个校验和确保数据完整性。
然后发送方不能不管接收方的承受能力,只顾着发。举个栗子,一个高速公路如果没有收费站,那么车辆就会一拥而入,此时不凑巧,发生了追尾事故,导致公路拥塞,如果不控制公路的进入车辆,那么整个高速公路都会变成“露天停车场”。说到这里你可能就明白了,TCP需要这样的“收费站”,而这个收费站就是“滑动窗口”。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ithIVwWy-1665280372036)(https://upload-images.jianshu.io/upload_images/27937678-b5cb94c6af0b85c5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
然后,平时在高速上的时候,细心的你注意到了:除了入口有个收费站,出口也有个收费站。TCP也是一样的,除了入口有发送方滑动窗口,出口处也设立有接收方滑动窗口。
收费站除了限制流速以外还有什么作用鸭?是不是要收费呢,毕竟这是国家修的路,不能白走是吧。
对于发送方滑动窗口(入口收费站),我们把数据包看成车辆,枚举它们的状态:
- 还未进入入口收费站车辆。对应的是下图Not Sent,Recipient Not Ready to Receive。这些数据属于发送端未发送,同时接收端也未准备接收的。
- 进入收费站,但未进入高速路。对应的是图中的Not Sent,Recipient Ready to Receive。这部分数据是发送端未发送,**但已经告知接收方的,这部分其实已经在窗口中(发送端缓存)**了,等待发送。
- 在高速公路上行驶的车辆。对应的是Send But Not Yet Acknowledged。这部分数据称为发送但没有被确认,数据被发送出去,没有收到接收端的 ACK,认为并没有完成发送,这个属于窗口内的数据。
- 到达出口收费站的车辆。对应的是Sent and Acknowledged。这些数据表示已经发送成功并已经被确认的数据,这些数据已经离开窗口了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wNI1dtvn-1665280372040)(https://upload-images.jianshu.io/upload_images/27937678-f770891aa86781d5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
对于接收方滑动窗口(出口收费站),类似发送端,接收端的数据有 4 个分类,因为接收端并不需要等待 ACK 所以它没有类似的接收并确认了的分类,情况如下
- 车辆还未到达出口收费站。对应Not Received:有空位,还没有被接收的数据
- 车辆到达出口收费站,但未完成缴费。对应Received Not ACK: 已经接收并,但是还没有回复 ACK,这些包可能输属于 Delay ACK 的范畴了。
- 车辆完成缴费,但不知道走哪条路。对应Received and ACK Not Send to Process:这部分数据属于接收了数据但是还没有被上层的应用程序接收,也是被缓存在窗口内。
- 车辆离开出口收费站。对应Received and ACK Send to Process。离开了窗口缓存。
这样讲是不是就很明白了,下面给出滑动窗口的正式定义。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u5U9qJwt-1665280372061)(https://upload-images.jianshu.io/upload_images/27937678-4a1837486f384e52.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
- Left edge和Right edge分别表示滑动窗口的左边界和右边界。
- Usable Window:表示窗口的缓冲区。
- Send Window :发送窗口, 这部分值是有接收方在三次握手的时候进行设置的,同时在接收过程中也不断地通告可以发送的窗口大小,来进行适应。
- Window Already Sent: 已经发送的数据,但是并没有收到 ACK。
滑动窗口所谓的“滑动”,并不是说窗口在动,而是因为数据在不断进入和离开窗口,也就是说真正“动”的是数据,下面一幅图就表示了这点:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6y24154V-1665280372062)(https://upload-images.jianshu.io/upload_images/27937678-8d6ea9a0ef3319ea.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
滑动窗口在TCP首部中的位置如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vgb3KxyM-1665280372063)(https://upload-images.jianshu.io/upload_images/27937678-fc12770c6fc9d11b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
RFC793对它的解释是"发送方希望接收到的以ACK标志开头的数据字节数"。滑动窗口是跟ACK一起的,因此ACK标志必须置为1,同时指定窗口大小。可以看到,滑动窗口大小通过16个bit来描述,所以变化范围0-65535(这个范围其实