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 排查流程
下面这张图是我自己总结的排查思路,你照着走基本不会漏:
这个流程我用了快十年,从 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 服务杀了,结果整台服务器需要重启。