Spring Boot 报端口被占用,netstat 却查不到进程,谁在抢?

文章来源声明: 原文作者:海上小飞龙; 来源站点:掘金; 原文链接:https://juejin.cn/post/7689004808923627560; 本文基于上述来源整理/加工,觅优补充点评,仅供技术学习交流。版权归原作者所有。
觅优短评

别急着改代码或换端口,先查系统排除范围。本文给出 netstat 与 netsh 的分工排查法,适合 Windows 上开发 Spring Boot 的工程师收藏备用。

启动报错,netstat 却查不到进程 -------------------

本地起一个 Spring Boot 项目,控制台突然报错:

Web server failed to start. Port 8123 was already in use。

照习惯打开 PowerShell 跑 netstat -ano | findstr :8123,想看看是哪个进程占着。

结果空空如也,没有任何输出。

这至少说明 netstat 没看到 8123 当前存在对应的监听项。

可 Spring Boot 偏偏还是启动失败了。

netstat 查不到,可能是系统排除了这个端口

开过 WSL2、Docker Desktop,或者其他依赖 Hyper-V、WinNAT 的虚拟化环境后,Windows 上可能会出现一些排除的端口范围。

启动项目时,如果恰好撞上这些范围,就可能出现端口无法绑定的情况。

Windows 会维护一组 Excluded Port Ranges。

这些端口不会像普通监听端口那样出现在 netstat 的监听列表里,但应用尝试绑定这些端口时,仍然可能失败。

Windows 把这段端口划成了禁区,并没有程序在监听它。

因此 netstat 里看不到任何进程,也就没法像普通端口占用那样顺着 PID 去定位。

当 Java、Node.js 或者 Python 等用户态程序尝试绑定这些端口时,Windows 可能直接拒绝这次绑定。

到了应用层,Spring Boot 可能仍然把这类绑定失败归纳成"端口已被占用"。

用 netsh 看系统到底留了哪些端口

普通进程正在监听端口时,可以用 netstat 查看对应的监听项和 PID;

如果查不到监听项,但应用仍然无法绑定,就可以进一步检查系统排除的端口范围。

要用另一套命令,以管理员身份打开 PowerShell,执行:

netsh interface ipv4 show excludedportrange protocol=tcp

如果应用使用 IPv6,还可以顺带检查对应的 IPv6 排除范围:

netsh interface ipv6 show excludedportrange protocol=tcp

输出长这样:

Protocol tcp Port Exclusion Ranges

Start Port    End Port
----------    --------
      1103        1202
      1403        1502
      5251        5350
      8082        8181
     50000       50059     *

每一行表示一段被排除的 TCP 端口范围。

假设你在自己的机器上看到:

      8082        8181

而你要用的端口是 8123,它正好落在这个区间里,这时 8123 无法绑定的原因就找到了。

找到排除范围后,先换到范围之外

很多教程一上来就让你换个端口,比如改成 8124。

这么做本身没有错,但如果不先确认排除范围,下一次换的端口照样可能落在另一个排除区间里。

如果已经确认 8123 落在系统排除范围内,就换一个不在任何排除范围内的端口。

比如当前排除范围是:

8082        8181

那么 8123 就不要再用了,可以改成 8200。

改完后再次执行 netsh interface ipv4 show excludedportrange protocol=tcp,确认 8200 不落在任何排除范围内,再启动 Spring Boot。

注意不要把"动态端口范围"和"排除的端口范围"混为一谈。

后者是 Windows 标记为排除的区间,应用通常不能正常绑定;

修改动态端口范围,并不会自动删除已经存在的 excluded port range。

少数情况下你确实想主动释放某个排除范围,微软提供了 delete excludedportrange 命令,但它要求起始端口和数量精确匹配当初创建的范围,如果这个排除范围是其他系统组件创建的,手动删除后也可能再次出现,所以本篇不把它当成标准做法。

回到 IDE 重新启动 Spring Boot,看到 Started Application in x seconds,问题就解决了。

两种排查方式,适用场景不一样

端口被占用,先别急着怀疑自己的代码。

netstat 查不到监听进程,但端口仍然无法绑定时,可以进一步检查 Excluded Port Ranges。

排查方式查什么适用场景
`netstat -ano`查看 TCP/UDP 连接、监听项和 PID怀疑有普通进程正在占用端口
`netsh interface ipv4 show excludedportrange protocol=tcp`查看系统排除的 TCP 端口范围查不到监听进程,但端口仍无法绑定