网工干货知识

超全学习笔记
当前位置:首页 > 干货知识

什么是TCP窗口缩放技术?

更新时间:2026年03月27日   作者:spoto   标签(Tag):

在TCP头部中,窗口大小字段的位数为16位。 使用这个字段时,TCP用户(无论是客户端还是服务器)都可以将其缓冲区大小设置为最多 2^16 = 65,536字节,即64KiB。 不过,现代终端设备(如手机、平板电脑、个人电脑等)的缓冲区中可用的内存要丰富得多。 在20世纪80年代,设计TCP协议时,16位字段就足够了。 不过,如今存储成本已经降低了,而且网络速度也变得非常快了。因此,情况已经发生了变化。 因此,如果某个端点在TCP连接中,其缓冲区中有超过64 KiB的内存可用,那么它是如何利用这个16位窗口大小字段来向对端端点传递这一信息的呢?

有两种可能的解决方案:

将窗口大小的字段从16位增加到30位。但实际上这是不可能实现的。因为全球范围内,有大量的设备都在使用TCP协议,所以无法在所有这些设备上同时更新这个字段的值。

2. 改变窗口大小的定义。使用比例因子,用TCP头部中仅有的16位字段来表示30位的窗口大小。这就是所谓的……窗口缩放。

TCP头部:

TCP头部

什么是TCP窗口缩放技术?

这种方法解决了“接收窗口”或“通告窗口”或“用户缓冲区”所带来的可扩展性问题,而无需增加TCP头部中“窗口”字段的大小(该字段为16位)。具体来说,它将“窗口”字段的定义扩展到了32位,然后使用一个“缩放因子”来将这32位的值存储在TCP头部的16位窗口字段中。这个缩放因子被存储在一个新的TCP选项中。窗口比例’. 

在TCP头部中,有一个选项字段。这个字段是为了容纳未来可能出现的各种优化而设计的。 窗口缩放功能同样利用了这一选项。 客户端首先会在SYN数据包中向服务器传递其缩放因子。 当服务器在“SYN”数据包中接收到客户端的缩放因子后,它会使用与“SYN+ACK”数据包中相同的选项字段来发送自己的缩放因子。而“SYN+ACK”数据包实际上是一种用于确认客户端所发起的连接请求的确认数据包。 有一个严格的限制:服务器应该忽略任何其他数据包中出现的“窗口比例”选项(除了客户端首先发送的SYN数据包)。也就是说,服务器不应提前共享自己的缩放因子。

假设客户端向服务器发送SYN数据包,并说明其缩放因子为2。然后,客户端在收到来自服务器的‘SYN+ACK’数据包时,会得知接收方的缩放因子为2。

现在,下一个数据包的发送方会告知其窗口大小为200字节。

那么,服务器会计算出客户端实际可用的缓冲区大小,其计算公式为:window_size × 22 = 800字节。

客户端首先确定自己的实际缓冲区大小,即800字节。然后,将该数值右移两次,之后将得到的新值存储在头部的窗口大小字段中,同时与服务器共享该值。

当服务器接收到缩放因子和窗口大小后,它会将该数值左移(即乘以2),从而得到客户端缓冲区实际的大小。

需要注意的是,当客户端在SYN数据包中向服务器传递其缩放因子时,该缩放因子在该数据包上并不适用。只有当服务器接收到该数据包后,并在SYN+ACK数据包中再次传递其缩放因子时,该缩放因子才具有实际意义。一旦客户端和服务器都提前知道了对方的缩放因子,那么从下一个数据包开始,他们就不需要在每个数据包中都传递缩放因子了。

我们可以更改窗口缩放因子吗?

完全有可能更新窗口缩放因子。 当客户端将来再次与服务器通信时,它可以将自己的窗口缩放因子再次发送给服务器。作为回应,服务器也会在SYN+ACK数据包中分享其窗口缩放因子。 那么,如果启用了TFO的话会怎么样呢?是的,此时,客户端可以在SYN数据包中,连同GET请求一起,向服务器发送其更新的窗口缩放因子。 作为对此的回应,服务器会在ACK数据包中分享其当前的窗口缩放因子,同时还会携带GET请求所需的数据。 还有另一种方法来更新窗口缩放因子。 客户应首先删除自己的 cookies。 当 Cookie 被删除后,就会进行初始的三方握手过程。之后,客户端就可以分享其新的窗口缩放因子了。

这个比例因子被存储在一个新的TCP选项中,该选项的名称是“”。窗口比例“shift.cnt”携带了缩放值。如果shift.cnt等于2,那么窗口大小字段的值就需要左移2位,这样才能得到真正的缓冲区大小。因此,缩放因子 = 2 * shift.cnt“shift.cnt”的值上限为14。因此,使用此选项时,可以通告的最大窗口大小为2^30 = 1 GiB。

在窗口大小字段中可以存储16位。而在shift.cnt变量中最多可以存储14位。因此,总共可以存储的位数就是16+14=30位。

如果“shift.cnt”的值大于14,那么TCP会记录这个错误,但仍然会使用“14”这个值,而不是“Window Scale”选项中指定的更大值。请注意:这个缩放因子仅适用于TCP头部中的“Window Size”字段,而不适用于在本地机器上存储“窗口值”的变量。

Linux命令行:

检查 Linux 内核中 TCP窗口缩放的默认设置

$ sysctl net.ipv4.tcp_window_scaling

预期输出结果(即,当TCP窗口缩放功能被启用时的情况):

$ net.ipv4.tcp_window_scaling = 1

禁用TCP窗口缩放功能(不建议这样做,但可以尝试一下,以便了解其工作原理后再重新启用该功能)。

$ sudo sysctl -w net.ipv4.tcp_window_scaling=0

预期输出:

$ net.ipv4.tcp_window_scaling = 0
              马上抢免费试听资格
意向课程:*必选
姓名:*必填
联系方式:*必填
QQ:
思博SPOTO在线咨询

相关资讯

即刻预约

免费试听-咨询课程-获取免费资料