Windows 网速慢:TCP 接收窗口自动调节被关掉,单线程卡在 7Mbps

这台机器修好只花了一条命令,单线程下载从 7Mbps 回到 171Mbps。命令先给,原因放后面讲。

解决办法

管理员身份打开 PowerShell 或 CMD,执行:

netsh int tcp set global autotuninglevel=normal

立即生效。已经建立的连接要重连才按新参数协商,重启一次更彻底。

改回去:

netsh int tcp set global autotuninglevel=disabled

四个档位的含义:

  • normal:系统按链路状况动态调窗口,绝大多数情况用这个
  • restricted:窗口增长受限,给老路由、异常网络留的备用档
  • highlyrestricted:几乎不长窗口,吞吐很低
  • experimental:激进增长,容易丢包,别碰

disabled 不在正常选项里。除非有明确的兼容理由,它不该出现。

效果验证

改之前改之后,用同一批源、同样时长测,别的变量不动。这台机器的实测(curl 单连接 15 秒):

测试源 修改前 修改后
清华 TUNA 6.54 Mbps 160.12 Mbps
中科大 6.79 Mbps 174.96 Mbps
华为云 12.18 Mbps 170.24 Mbps
南大 9.38 Mbps 27.39 Mbps
四源并发 40.20 Mbps 273.00 Mbps

南大那个源本身偏慢,其他三个都跑起来了。十分钟后第二轮复测 153.6 / 221.5 / 198.4 Mbps,稳定,不是瞬时抖动。

自己测,用系统自带的 curl(Win10 1803 之后都有):

curl.exe -L -o NUL -s -w "下载速度: %{speed_download} B/s`n" --max-time 15 "换成任意几百MB文件的直链"

--max-time 15 会在 15 秒后中断,speed_download 照样输出。多换几个源各测一次:单源慢、多源并发能上去,基本就是窗口或拥塞参数的问题,带宽没毛病。测的时候别同时跑两台机器,同一出口互相抢带宽,测出来没意义。

为什么这一行能决定速度

先说这台机器的实测背景。联想笔记本,Windows 11,出口是手机热点,5GHz 信道 149,信号 -40dBm,协商 1201Mbps,收发包零错误零丢弃。到网关 3-5ms,到 223.5.5.5 平均 26ms,100 个包一个没丢,到清华镜像 68ms。无线这层干净,延迟正常,问题只出在速度上。

同一时间点,curl 单线程拉四个不同源的镜像,每个 15 秒:

  • 清华 TUNA:769 KB/s
  • 中科大:712 KB/s
  • 华为云:1235 KB/s
  • 南大:951 KB/s

四条同时开,合计 3464 KB/s,约 27Mbps。

整条链路能跑 27Mbps,任何单独一条连接却都被压在 5-10Mbps。热点限速不是这个表现,限速是总量封顶、单流能吃满配额。这里多开能叠加、单开跑不动,说明限制在每条 TCP 连接内部。

一条命令定性:

netsh int tcp show global

输出里这一行不对:

接收窗口自动调节级别                       : disabled
窗口缩放启发                               : disabled

Windows 默认是 normal。这台是 disabled,连窗口缩放启发一起关了。系统默认值里没这一项,说明有人手动改过,或某个工具动过手脚。

原理说简单点:TCP 带确认,接收方每次回 ACK 会告诉发送方「我还能收多少字节」,这个数字就是接收窗口。发送方在收到确认前,最多只能发这么多未确认数据,超了就得等。所以单条连接的极限速度大约是:

速度上限 ≈ 接收窗口 ÷ 往返延迟(RTT)

这个乘积叫带宽时延积。千兆带宽加 70ms 延迟,要 8.75MB 窗口才填得满;万兆同样延迟要 87MB。

而 TCP 头里窗口字段只有 16 位,最大 65535 字节,就是 64KB。想超过 64KB,得在三次握手时协商窗口缩放因子(RFC 1323),把窗口乘 2 的 n 次方,最大能到 1GB。这个协商靠的就是被关掉的那个「窗口缩放启发」。

自动调节关了,窗口固定 64KB,缩放也不谈,每条连接上限锁死:

65536 字节 ÷ 0.07 秒 ≈ 936 KB/s ≈ 7.5 Mbps

实测单连接 6.5-12Mbps,和算式对上了。多开能叠加,是因为窗口按连接算,所以浏览器开网页还算流畅;碰上单线程下载、游戏更新、网盘客户端、在线视频,速度就塌到个位数。

谁改的

三种来源最常见:

  1. 各种「网络优化」「降低延迟」的 bat 和注册表脚本。这类脚本抄来抄去,常带 autotuninglevel=disabled,理由写的是「固定窗口降低延迟」。固定窗口确实让行为可预测,代价是吞吐砍到十分之一。
  2. 游戏加速器。部分加速器为了接管流量会改 TCP 全局参数,卸载后不还原。
  3. 过时的优化教程。有些教程针对的是十几年前的窄带或特定路由器兼容问题,被当成通用方案传到现在。

这台机器还装着火绒残留(NDIS 过滤驱动 hrndis6 仍在跑)、Wireshark 的 Npcap 抓包驱动、ToDesk 三个进程,都会给每个包多加一道处理。但修完 TCP 参数后单连接已经 200Mbps,它们不是瓶颈,暂时没动。

几条边界

修完不等于网速无限。这台机器的出口是手机热点,四源并发 273Mbps 就是链路上限,参数修好只能让单流跑满它。机器上有 2.5G 有线网口一直空着,插网线或换正规宽带才是根治,尤其打游戏。

这类改动不会自己恢复。我查了计划任务、加速器服务、注册表启动项,没发现会把参数改回去的东西。改完过几天又慢,得去查谁在定时执行 netsh。

别信「关闭自动调节能降低延迟」。延迟由路由、拥塞、排队决定,窗口调小只会让传输次数变多、重传变多。吞吐砍到十分之一,换来的抖动改善连测都测不出来。

卸载杀软要卸干净。火绒卸掉后 NDIS 过滤驱动还在跑的情况很常见,driverquery /v | findstr /i huorong 这类命令能看到残留。清理网络栈有断网风险,留到最后做,备好回滚。

总结

网速慢的源头很多,运营商、路由器、无线干扰、DNS、浏览器、后台下载、代理软件都能造成慢。这台机器的数据把范围压得很小:无线干净、延迟正常、丢包为零、多连接能叠加,只有单连接上不去。

「总量够、单流不够」这种形状,基本只会出现在 TCP 参数被改坏的时候。一条 netsh int tcp show global 定性,一条命令修好,前后差二十多倍。

麻烦的是排查思路。很多人网速慢第一反应换路由器、找运营商、重装系统,从头到尾没看过这一行输出。把 autotuninglevel=disabled 抄进「优化脚本」的人,可能自己都不知道这一条会砍掉九成吞吐,受害者半年后还在怀疑宽带不行。下次网速不对劲,先看这一行。