借助wireshark深入分析---tcp传输窗口

tcp传输窗口解析——借助wireshark深入分析

tcp传输报文时,会有“往返”的需要。因为发包之后并不知道对方能否收到,要一直等到确认包到达,这样就花费了一个往返时间。假如每发一个包就停下来等确认,
一个往返时间里就只能传一个包,这样的传输效率太低了。最快的方式应该是一口气把所有包发出去,然后一起确认。但现实中也存在一些限制:接收方的缓存(接收窗口)可能一下子接受不了这么多数据;网络的带宽也不一定足够大,一口气发太多会导致丢包事故。所以,发送方要知道接收方的接收窗口和网络这两个限制因素中哪一个更严格,然后在其限制范围内尽可能多发包。这个一口气能发送的数据量就是传说中的 TCP发送窗口。发送窗口对性能的影响有多大?一图胜千言,下图显示了发送窗口为 1个 MSS(即每个 TCP包所能携带的最大数据量)和 2个 MSS时的差别。在相同的往返时间里,右边比左边多发了两倍的数据量。而在真实环境中,发送窗口常常可以达到数十个 MSS。


1.每个包的 TCP层都含有“ window size:”(也就是 win =)的信息。这个值表示发送窗口的大小吗?

这不是发送窗口,而是在向对方声明自己的接收窗口。

从下截图中可以看到, 61.135.169.121 向 192.168.1.121 声明自己的接收窗口是 772字节。 192.168.1.121 收到之后,就会把自己的发送窗口限制在 772字节之内。很多教科书上提到的滑动窗口机制,说的就是这两个窗口的关系,本文就不再赘述了。假如接收方处理数据的速度跟不上接收数据的速度,缓存就会被占满,从而导致接收窗口为 0。接收方持续向 发送方 声明自己的接收窗口是 win = 0,所以 发送方的发送窗口就被限制为 0,意味着那段时间发不出数据。


其中在截图中看到的win size 和 Calculated Windows Size ,可以看到这两个值是不一样的。
再关注一下下面的那个字段值:“Window size scalling factor”,
会有一个这样的算术关系:
win size * win size scalling factor = calculated win size
这里也就是 772 * 32 = 24704

window size value表示报文的值,calculated window size表示放大后的值,也就是实际可用的值,而 scalling factor 就相当于放大的倍数,具体这个字段代表的含义,可以往下看(第5点有写)。

2.在包里看出发送窗口的大小呢?

很遗憾,没有简单的方法,有时候甚至完全没有办法。因为,当发送窗口是由接收窗口决定的时候,我们还可以通过“ window size:”的值来判断。而当它由网络因素决定的时候,事情就会变得非常复杂,今天这里暂时不涉及,后面会单独拿出来讨论。大多数时候,我们甚至不确定哪个因素在起作用,只能大概推理。比如,如果接收方声明它的接收窗口等于 0,那接收窗口肯定起了限制作用(因为不可能再小了),因此可以大胆地判断发送窗口就是 0。还可以观察如果发送方发送了2个包就需要等待确认,那可能发送窗口就是这两个包的长度。

3.发送窗口和 MSS有什么关系?

发送窗口决定了一口气能发多少字节,而 MSS决定了这些字节要分多少个包发完。举个例子,在发送窗口为 16000字节的情况下,如果 MSS是 1000字节,那就需要发送 16000/ 1000 = 16个包;而如果 MSS等于 8000,那要发送的包数就是 16000/ 8000 = 2了。

4.发送方在一个窗口里发出 n个包,是不是就能收到 n个确认包?

不一定,确认包一般会少一些。由于 TCP可以累积起来确认,所以当收到多个包的时候,只需要确认最后一个就可以了。可能会存在客户端用一个包确认了它收到的 10个包。这个就需要根据ack报文的num 进行确定了。

比如如下截图可以看到ack num = seq num + len
分别用绝对 seq num 和相对 seq num 看一下:


这样就可以确定这个ack报文是确认的哪个seq报文,一个ack报文确认多个请求报文的场景,实在是没有合适的场景报文。

5.经常听说“ TCP Window Scale”这个概念,它究竟和接收窗口有何关系?

在 TCP刚被发明的时候,全世界的网络带宽都很小,所以最大接收窗口被定义成 65535字节。随着硬件的革命性进步, 65535字节已经成为性能瓶颈了,怎么样才能扩展呢? TCP头中只给接收窗口值留了 16 bit,肯定是无法突破 65535 (216 − 1)的。 1992年的 RFC 1323中提出了一个解决方案,就是在三次握手时,把自己的 Window Scale信息告知对方。由于 Window Scale放在 TCP头之外的 Options中,所以不需要修改 TCP头的设计。 Window Scale的作用是向对方声明一个 Shift count,我们把它作为 2的指数,再乘以 TCP头中定义的接收窗口,就得到真正的 TCP接收窗口了。如下图,这是一个很久版本的wireshark截图了,从底部可以看到 10. 32. 106. 159告诉 10. 32. 106. 103说它的 Shift count是 5。 25等于 32,这就意味着以后 10. 32. 106. 159声明的接收窗口要乘以 32才是真正的接收窗口值。


如果使用新版的wireshark,就是前面的那张图,显示上已经有所不同了,不过字段含义还是一样的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章