一. 原理
TCP是全双工通信,因此每一方的滑动窗口都包括了接收窗口+发送窗口,接收窗口负责处理自己接收到的数据,发送窗口负责处理自己要发送出去的数据。滑动窗口的本质其实就是维护几个变量,通过这些变量将TCP处理的数据分为几类,同时在发送出一个报文、接收一个报文对这些变量做一定的处理维护。
发送窗口如上图 :
(1)N是发送窗口的起始字节,也就是说:字节序号 < N的字节都已经发送出去且已经收到ack,确认无误了;
(2)nextSeq就是下一次发送报文的首部Seq字段(Seq即第一个字节的序号,这些这里不讲了),表示字节序号在 [N,nextSeq)区间的都已经使用过,发送出去了,但是还未收到ack确认;
(3) N+size就是窗口的最后一个可用字节序号,size是发送窗口的大小,就是每次接收到的报文中的Win字段的值,Win字段其实就是对方接收窗口的大小。
如何让维护这几个值呢?
(1)每接收到一个一个报文要做如下事情:检查接收报文的ack,将N 置为 ack,即往前移到ack这个值;读取报文中的Win字段值,即对方的最新接收窗口大小,从而更新N+size的值。
(2)每发送一个报文,就更改nextSeq的值,发送了多少个字节就把nextSeq往前移多少,但是不要超出N+size。
下面看接收窗口:
同样是维护几个关于字节序号的变量,与发送窗口类似,只不过接收窗口的字节序号都是接收到的字节。几个变量的意义如下:
(1)J1表示:字节序号 < J1的字节已经接收到了,即已经发出ack确认了,也可以说可以给程序使用了。
(2)J2表示:[J1,J2)区间的字节已经完整、有序的接收到了,随时可以供程序读取,但只是还没有发出ack,进行确认。
(3)J3就是接收窗口的最后一个可接收字节,超过J3的字节发来是拒绝接收的(一般也不会收到,因为发送窗口的大小是根据接收窗口来的,不可能回超过)。
如何维护呢?
(1)发送一个报文时:将J2的值填入报文首部的ack字段,然后J1移动到J2,告诉对方你发来的字节序号小于J2的那些,我已经都正确接收到且使用了;将 (J3-J2) 的差值填入首部Win字段,告诉对方我还有多 大空间可以接收。
(2)接收到一个报文时,如果报文顺序没出错,则将移动J2,接收到多少字节就移动多少。如果报文按序到达,下一个收到的报文的Seq值就应该等于J2,如果不相等说明中间有报文丢失了,就不移动J2,从 而接下来发送的报文ack一直是同一个:J2,也就是重复确认,相应的又有快重传(扯远了,不详细说了)。
3. 滑动窗口原理总结
因为窗口的起始值在开始后就会慢慢的增加,也就是右移,所以这也是滑动窗口名字的由来。实际上就是在接收报文、发送报文维护几个关于ack 、字节序号、seq(报文起始字节序号)的变量值。关于ack、seq、WinSize总结如下:
(1)发送报文ack是怎么来的,接收到报文时ack又是怎么用的:
发送报文时从接收窗口拿J2的值填到报文首部的 ack;接收报文时拿到ack后将发送窗口的起始值N更新为ack。
(2)发送报文seq是怎么来的,接收到报文时seq又是怎么用的:
发送报文时从发送窗口拿到nextSeq的值填到报文首部的seq字段;接收到报文后查看报文的seq字段是否是接收窗口的J2,是就根据报文长度将J2连续右移。
(3)发送报文Win是怎么来的,接收到报文时Win又是怎么用的:
发送报文时,从接收窗口拿到 (J3-J2)的这个差值填到首部的Win字段;接收到报文时拿到首部的Win字段的值,假设为size,则更新发送窗口的结束位置为 N+size
二. 作用
我们知道,网络层实际上就是一个数据报网络,本身是不面向连接的,也不提供可靠有序完整的服务。udp直接使用数据报网络,所以它只是提供尽力交付的服务,在传输过程中数据包可能会丢失。那么为什么TCP同样是使用数据报网络,却能够实现面向连接的可靠传输服务呢?实际上,是因为TCP的可靠传输不是依靠下层的网络层完成的,完全是在传输层上,在软件层面完成的,具体体现在TCP协议有收到确认、有超时重传、有重复确认-快重传等额外步骤。
正是因为收发数据报相比于udp多了这么多限制,所以才实现了可靠传输的服务,这些额外的步骤也带来了不少问题:需要在首部字段多设置不少的字段用来完成那些步骤,多做的步骤会有时间、资源开销等。这些首部字段最重要的就是 ack 、字节序号、seq,这是保证能正确的重传丢失报文的基础。
但是,有了这些也只能这样做:发送报文,等待对方确认,收到确认后继续发下一报文,效率非常低。而有了滑动窗口,通信双方就不用发送一个报文后,收到此报文的确认后再发送下一个报文,而是可以连续发送多个报文,只要别超过窗口大小限制;还有就是:TCP开销比udp大,一旦网络拥塞或报文丢失又会造成报文重发,而这些重发又加重了拥塞,所以TCP里要严格控制发送速率防止网络拥塞,滑动窗口根据接收方的Win大小很好的限制了发送方的发送速率。
总结就是:(1)滑动窗口允许发送方连续发送多个报文(2)根据对方接收窗口大小限制发送方的发送速率,防止拥塞
(注意:实际中并不一定按对方接收窗口rwnd大小来决定发送速率,因为没有考虑网络拥塞情况。拥塞控制中同样会决定发送窗口cwnd大小,最后发送时取 MIN(cwnd,rwnd))
三. 过程示例
给个书上的示例:
B发送的的rwnd就是报文头部Win字段的值。解释个小问题:为什么前面说发送窗口的结束位置是N+size,而不是nextSeq+size?因为[N,nextSeq)这些字节是发送出去但未收到确认的,是随时有可能重发的,因此结束位置要从N算起,到N+size。
原文地址:https://www.cnblogs.com/shen-qian/p/12111666.html