3. Windows 排查工具:使用 netstat -ano 查看端口占用

说到端口排查,Windows 上最趁手的工具就是 netstat。我入行那会儿,图形界面工具还没这么普及,全靠这个命令行活。这么多年过去了,它依然是我排查端口问题的第一选择。

说白了,netstat -ano 就是一张「网络连接实时快照」。它能告诉你:哪个端口开着、谁在用、状态如何。今天我们就把它彻底讲透。

3.1 基础命令:-ano 参数到底什么意思?

很多新手一上来就敲 netstat -ano,但不知道每个字母代表什么。我习惯把参数拆开记:

参数 含义 为什么重要
-a 显示所有连接和监听端口 不加这个,你看不到 LISTENING 状态的端口
-n 以数字形式显示地址和端口 跳过 DNS 解析,速度更快,结果更干净
-o 显示关联的进程 PID 这是定位「谁占用了端口」的关键
我的习惯: 我一般直接敲 netstat -ano | findstr :8080。加个 findstr 过滤,省得看一堆无关信息。你想想看,如果服务器上有几百个连接,一条条翻多累。

3.2 实战:定位端口 8080 被谁占了

假设你的 Tomcat 启动报错,说 8080 端口被占用。我们来走一遍完整流程。

第一步:查占用

C:\Users\admin> netstat -ano | findstr :8080

  TCP    0.0.0.0:8080    0.0.0.0:0    LISTENING    12345
  TCP    [::]:8080       [::]:0       LISTENING    12345

看到了吗?PID 是 12345,状态是 LISTENING。注意这里出现了两条记录——IPv4 和 IPv6 各一条,但 PID 相同,说明是同一个进程在监听双栈。

第二步:查进程

C:\Users\admin> tasklist | findstr 12345

java.exe                     12345 Console                    1    256,784 K

嗯,是个 Java 进程。如果你想知道更详细的信息,可以用 tasklist /FI "PID eq 12345" /V,能看到启动路径和用户名。

我曾经踩过的坑: 有一次我查到一个端口被 PID 4 占用,也就是 System 进程。我以为是系统进程就没管,结果折腾了半天。后来才发现,PID 4 可能是某个驱动程序或服务通过内核句柄占用了端口。这时候 netstat -ano 就查不到进程名了,得用 netsh 或者工具进一步深挖。

3.3 输出列解读:每一列都别忽略

我们拿一条典型输出来拆解:

  Proto  Local Address          Foreign Address        State           PID
  TCP    192.168.1.10:443       10.0.0.5:52341         ESTABLISHED     6789
  • Proto: 协议类型,TCP 还是 UDP。UDP 没有状态,所以 State 列是空的。
  • Local Address: 本机 IP 和端口。如果是 0.0.0.0:80,表示监听所有网卡的 80 端口。
  • Foreign Address: 对端地址。0.0.0.0:0 表示还没建立连接,常见于 LISTENING 状态。
  • State: 连接状态。常见的有 LISTENING、ESTABLISHED、TIME_WAIT、CLOSE_WAIT。
  • PID: 进程标识符。这是定位的钥匙。
重点: 排查端口占用时,重点关注 LISTENING 状态的记录。只有这个状态才表示端口正在被某个进程「霸占」着。ESTABLISHED 只是正在通信,不会阻止其他程序监听。

3.4 常见状态:TIME_WAIT 和 CLOSE_WAIT 怎么处理?

你可能会看到大量 TIME_WAIT 状态的连接。别慌,这通常是正常的。我解释一下:

状态 含义 是否影响端口占用 处理建议
LISTENING 端口正在被监听 是,其他程序无法使用 找到 PID,决定是否终止
ESTABLISHED 连接已建立,正在通信 否,不影响新监听 正常状态,无需处理
TIME_WAIT 主动关闭后等待 2MSL 通常不影响,但占用临时端口 系统自动回收,不用管
CLOSE_WAIT 被动关闭,等待应用关闭 可能泄漏资源 检查应用代码,及时 close

我记得有一次线上服务出现大量 CLOSE_WAIT,导致连接数飙升。用 netstat -ano | findstr CLOSE_WAIT 一查,发现全是某个 HTTP 客户端没正确释放连接。说白了,就是代码里忘了 response.close()。

3.5 进阶技巧:组合拳打法

光用 netstat 有时候不够,我一般搭配这几个命令:

  • 按端口范围过滤: netstat -ano | findstr ": [1-9][0-9]*$" —— 正则匹配端口号,适合批量排查。
  • 按进程名查端口: 先 tasklist | findstr nginx 拿到 PID,再 netstat -ano | findstr 1234。
  • 导出到文件分析: netstat -ano > ports.txt,然后用 Excel 或 Notepad++ 慢慢看。我处理过一台有 5000+ 连接的服务器,命令行翻页太痛苦了。
小技巧: 如果你经常查端口,可以写个批处理:netstat -ano | findstr /i "listening"。这样只看监听中的端口,信息量少一半,效率翻倍。

3.6 知识体系:netstat 排查流程

下面这张图是我自己总结的排查思路,你照着走基本不会漏:

netstat -ano 端口排查流程图 发现端口冲突 执行 netstat -ano | findstr :端口 记录 PID(如 12345) tasklist | findstr 12345 是否可终止? taskkill /PID 12345 /F 修改应用端口配置 问题解决 ✓ 无法终止?改配置

这个流程我用了快十年,从 Windows Server 2003 到 2022,从来没掉过链子。你只要记住:先查 PID,再查进程,最后决定是杀进程还是改配置。

3.7 避坑指南:我踩过的几个雷

  • 不要只看端口号: 有一次我查 3306 端口,发现被 PID 4 占用,以为是 MySQL。结果是个系统服务。后来用 netsh http show servicestate 才找到真正的元凶——是 Windows 的 HTTP 内核驱动。
  • 管理员权限: 有些端口(比如 1-1024)需要管理员权限才能看到完整信息。我习惯直接「以管理员身份运行」CMD,省得查半天发现是权限问题。
  • UDP 端口没有状态: 很多新手查 UDP 端口时发现 State 列是空的,以为命令没生效。其实 UDP 是无连接的,没有 LISTENING 状态。只要看到 PID 就说明端口被占用了。
重要提醒: taskkill /F 会强制终止进程,可能导致数据丢失或服务异常。我建议你先用 tasklist /V 看看进程的详细信息,确认不是关键系统进程再动手。曾经有个同事在生产环境上把 RPC 服务杀了,结果整台服务器需要重启。