和其他操作系统一样,Windows 的端口占用问题是老生常谈的话题了。不过,由于 Hyper-V 技术的出现,端口占用的原因也不只一种,导致原来的方法可能不奏效。因此记录一下 Windows 端口占用的两种情况以及对应的解决方法。

# 查询是否被其他应用占用

在管理员下的 powershell(2202 年了,也该学一下 powershell 了):

# 管理员不是必需,但不用管理员可能看不到其他用户的进程?
netstat -ano | Select-String "8080"

查询结果

11284 是 Process ID,可以直接 kill 掉,也可以看看是什么。

ps -PID 11284
kill 11284

查询结果

# 查询是否被 Hyper-V 占用

以前的 Windows 在上面一步基本就能结束了,但现在是 2202 年,Docker 和 WSL 2 大行其道,干开发的应该都用着 Hyper-V。而 Hyper-V 会保留一些端口,其他应用就不能占用了。

使用下面这行命令查询 Hyper-V 占用的端口:

netsh interface ipv4 show excludedportrange protocol=tcp

查询 Hyper-V 占用的端口

图上没有 * 的就是 Hyper-V 分配并占用的端口。而加了 *Administered port exclusions 就是我们保留的端口, Hyper-V 不会再占用。

# 方法一:改变 Hyper-V 的分配范围

使用下面这行命令可以查询 Hyper-V 的分配范围:

netsh int ipv4 show dynamicport tcp

我们将分配范围改为 40000-49999(共 10000 个端口):

netsh int ipv4 set dynamicport tcp start=40000 num=10000

重启以后可以看到, Hyper-V 会从 40000 开始分配端口。

Hyper-V 从 40000 开始占用端口

MSDN 的文档 (opens new window)里表示,最小端口范围是 255。

2022.4.14 更新:在我只给 Windows 分配了 255 和 1000 个端口的这几天里,我发现我的梯子客户端开始频繁抽风,具体表现在 Chrome 经常加载不出国内外的网页、npm 安装依赖会报错(代理端口) Address Already In Use。最后只能乖乖把范围改回 40000-49999.
这个问题在我两台 Windows 11 电脑上都是 100% 复现。我猜测是端口太少,导致 Hyper-V 短时间随机占用端口,但在 MSDN 的文档里没有提到端口过少的后果,谷歌也没有结果,毕竟大部分人(包括我最开始接触到 Hyper-V 端口占用的几年)用的都是下面保留端口的方法。
但是还是修改范围的方法好用,因为 40000-50000 之间的高位端口没什么程序会长期占用,实在有,就再用下面的方法保留一下就行。

Address Already In Use

# 方法二:保留某些端口

如何在已有的分配范围下,保留部分端口范围呢?在管理员下的 powershell 使用下面这行命令:

# 保留 7962 开始的 100 个端口(即 7962-8061)
netsh int ipv4 add excludedportrange protocol=tcp startport=7962 numberofports=100

7962-8061 已为我们保留

如果执行的时候遇到 netsh error: The process cannot access the file because it is being used by another process,可以尝试重启电脑。如果重启也不行,可以试试关掉 Hyper-V、重启、保留完端口再打开 Hyper-V、重启。

# 关掉 Hyper-V
dism.exe /Online /Disable-Feature:Microsoft-Hyper-V
# 开启 Hyper-V
dism.exe /Online /Enable-Feature:Microsoft-Hyper-V /All

Reference: