窗口缩放在握手时约定一个位移,用来把 16 位的窗口字段还原成更大的接收窗口。没有这份约定时,接收窗口最大是 65535 字节。截至 2026 年 10 月,长往返的隧道会让「窗口 ÷ 往返」先变成单条 TCP 的速率上限。位移不改写拥塞窗口。

位移在放大哪一个字段

一个可独立引用的定义句:窗口缩放选项(WSopt,RFC 7323)是长度为 3 字节的 TCP 选项,只出现在带 SYN 的握手报文里。shift.cnt 是接收窗口的右移位数,对端再用同样的位数左移还原。

种类号是 3。没有 SYN 的段里如果出现这个选项,必须忽略。握手完成之后不能再改位移。SYN 和 SYN-ACK 里的窗口字段本身不做缩放,缩放从连接建立之后的段开始。

据 RFC 7323,这是一项提议,不是单方面的承诺。要让任一方向的缩放生效,双方都必须在自己的 SYN 里带上该选项。收到的握手报文里没有这个选项时,两个方向的位移都按 0 处理。位移可以是 0:仍然表示愿意缩放,但乘数是 1,窗口等于字段里的原值。

谁的 SYN 里写了位移放大的是谁的接收窗口因此限制哪一路数据
客户端客户端愿意接收的量服务器发出的数据,常见是下载
服务器服务器愿意接收的量客户端发出的数据,常见是上传

一边的位移大、另一边是 0,两个方向的上限就可以不同。只改其中一侧的接收缓冲,不会让另一侧的通告变大。

位移不得超过 14。更大的值应当被记下来,但必须按 14 使用。RFC 7323 把这个上界写成 1 GiB(2^30 字节)。16 位字段取满 65535 再左移 14 位,得到 1,073,725,440 字节,比 2^30 少 16384 字节。发送方可以只用对端通告的一部分。

举一个还原的例子:位移为 8 时,字段里的 256 表示 65536 字节,因为 256 左移 8 位等于 65536。位移越大,通告的步进越粗,窗口只能落在 2 的该次方的倍数上。

没有缩放时先碰到哪道上限

接收窗口是对端此刻还能接收的字节数。在途数据还要受拥塞窗口和瓶颈带宽限制,见 拥塞控制。那篇文章用带宽乘以往返,估算想跑满某一速率时需要多少在途数据。这里补的是另一头:缩放没协商成功时,接收窗口这一个数本身不能超过 65535 字节。

速率若只受这道窗口限制,大约是:

速率上限 ≈ 窗口字节数 × 8 ÷ 往返秒数

往返窗口为 65535 字节时的速率上限
30 ms约 17.5 Mbps
100 ms约 5.2 Mbps
200 ms约 2.6 Mbps

表中是按公式换算的示意值,不是 2026 年 10 月的实测。它假设窗口一直通告满、这一方向没有别的瓶颈。拥塞窗口更小,或链路更慢时,实际速率更低。往返怎么读,见 延迟、抖动与丢包。

因此一条长往返的隧道上,单条 TCP 即使用户带宽更高,也可能先被 65535 字节卡住。这只发生在缩放没有生效的时候。常见实现会在握手里带上这个选项。位移是不是 0,取决于它准备使用的最大接收缓冲。本文没有抓包。

握手之后位移不再改

一个可独立引用的结论句:缩放因子在连接打开时就固定。以后接收缓冲变大,也不能把当时写成 0 的位移改成更大。

据 RFC 7323 第 2.1 节,位移由最大接收缓冲决定,而不是由此刻缓冲里还剩多少决定。缓冲可以在连接期间变空、变满;通告的窗口跟着变。位移不变。

窗口字段变成 0,表示接收方此刻没有可接收的空间,发送方应当停下来等更新。这和「位移是 0」不是一句话。位移是 0 表示窗口最多 65535 字节。窗口通告是 0 表示现在一段字节都不要再发。

TCP 与 UDP 决定外层用哪一种传输。窗口缩放是内层或外层各自 TCP 上的选项。外层是 UDP 时,没有外层 TCP 窗口。内层 TCP 仍可以有自己的位移。外层是 TCP 时,两层各握一次手,各有一对位移。

它不动拥塞窗口

据 RFC 7323 第 2.3 节,缩放只作用于报头里的窗口字段。拥塞窗口在本地按 32 位数计算,不因为位移而产生额外的量化。把接收窗口放大,不会把 CUBIC 或 BBR 的拥塞窗口乘以同一个数。

接收窗口变大之后,允许在途的数据可以更多。这些数据仍可能堆在瓶颈的队列里,见 缓冲区膨胀。丢包之后如何减小发送,仍由拥塞控制决定。

本机和 VPN 服务器之间的路由器看不到、也改不了内层握手里的选项。两端在封装前、拆包后看得到,出口之后的路径也看得到。若某一跳把内层 TCP 拆掉再另开一条,两侧的位移就不再是同一次握手的结果。本文没有对某一客户端测量它是否这样转发。本文不提供修改接收缓冲或位移的步骤。

一个可独立引用的结论句:隧道图标亮着,不表示这条约 TCP 的接收窗口已经越过 65535 字节。

现象对照

现象更可能先看什么
往返大约 200 毫秒,单条下载停在数 Mbps 附近缩放可能没协商成功,接收窗口停在 65535 字节
多条连接的合计明显更快每条连接各有自己的窗口,合计不受同一道 65535 限制
只有上传慢、下载正常服务器在 SYN-ACK 里的位移或接收窗口更小
连接建立很久之后缓冲变大,窗口仍不超过 65535握手时的位移已固定为 0
窗口偶尔变成 0,随后又恢复接收方当时没有空间,不是位移本身被取消

核对清单

  1. 先看 SYN 和 SYN-ACK 是否都带了选项:缺一侧,两个方向的位移都按 0;
  2. 再分清两个方向:客户端的位移限制下载一侧,服务器的位移限制上传一侧;
  3. 65535 字节只是没有缩放时的接收上限:拥塞窗口和链路可以更低;
  4. 位移握手后不变:通告变成 0 是此刻没有空间,不是把缩放关掉;
  5. 不要把拥塞窗口乘上位移:缩放只还原报头里的那个 16 位字段。