Windows 网速慢:TCP 接收窗口自动调节被关掉,单线程卡在 7Mbps
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,和算式对上了。多开能叠加,是因为窗口按连接算,所以浏览器开网页还算流畅;碰上单线程下载、游戏更新、网盘客户端、在线视频,速度就塌到个位数。
谁改的
三种来源最常见:
- 各种「网络优化」「降低延迟」的 bat 和注册表脚本。这类脚本抄来抄去,常带 autotuninglevel=disabled,理由写的是「固定窗口降低延迟」。固定窗口确实让行为可预测,代价是吞吐砍到十分之一。
- 游戏加速器。部分加速器为了接管流量会改 TCP 全局参数,卸载后不还原。
- 过时的优化教程。有些教程针对的是十几年前的窄带或特定路由器兼容问题,被当成通用方案传到现在。
这台机器还装着火绒残留(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 抄进「优化脚本」的人,可能自己都不知道这一条会砍掉九成吞吐,受害者半年后还在怀疑宽带不行。下次网速不对劲,先看这一行。