使用wireshark抓包分析 TCP handshake 中 window scale 参数

Window scale简析

首先TCP的窗口有两种,发送窗口和接收窗口。这里我们主要讨论接收窗口,在TCP通信中,发送方的TCP报头中会包含一个窗口信息,这个窗口是指发送方的接收窗口的大小,当接收方进行应答时,发送的在途数据不能超过窗口大小,否则会造成丢包。

下面我们讨论下Window scale的具体作用。

在TCP的报头中,有一个16bit的字段是表示window的大小的,而2^16 = 65536,即由于字段的长度,窗口最大为64KB,显然对于现在动辄1000Mbps的带宽,这个大小是远远无法满足实际需求。如果要修改该字段的长度,则对TCP的兼容性会造成比较大的影响,因此采用了Window scale的方法。即在TCP的报头的option 中增加一个Window scale,计算方式如下:
实际的窗口大小 = (window size value) X (2^(Window scale))

这样在实际交互过程中就可以采用比较大的实际窗口了。

TCP 握手

tcp的三次握手过程如下图所示。12号包是客户端发送的SYN握手请求包;15号包是服务器返回的SYN/ACK包,即是应答12号包;17号包是客户端发送的ACK包,即是对15号包的应答。

wireshark 设置rtp 负载类型 wireshark tcp window full_TCP


先看下图的第一个包,这个是发起方的SYN请求包,从图中TCP的报头中可以看出,windows size value = 65535,即为协商window scale 情况下的最大值。而window scale = 7,即之后的实际窗口要用窗口大小乘以128。

wireshark 设置rtp 负载类型 wireshark tcp window full_客户端_02


再看下图中服务器的应答包SYN/ACK,图中window size value = 8190,即告知客户端后面发送的在途数据不要超过这个值。window scale = 7,同样后面计算实际窗口时,要乘上128。

wireshark 设置rtp 负载类型 wireshark tcp window full_窗口大小_03


最后看下一客户端返回的ACK包,如下图所示。由于之前双方已经交换了各自的window scale,因此之后的传输中,对窗口的计算都要乘以相应的值,这里看可以看到,客户端告知服务器,window size value = 2048,则客户端在发送数据时不能超过2048X128=262144,这样就保证不会因为在途数据超过窗口大小而导致丢包。

wireshark 设置rtp 负载类型 wireshark tcp window full_TCP_04


综述,window scale 看起来是适应网络带宽的不断增加,而采用的补丁方案,从现在看主要是TCP当时设计时,未考虑到目前的情况。但是这也不能说是当时设计的问题,毕竟能穿越时空预知未来的人不多。不过从未来的发展的趋势来看,TCP要想继续在未来发挥作用,变革必不可少,但是最终可能也会退出历史舞台。