本地起一个服务,端口没换,直接报地址已被占用。
OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次
换成nginx起不来,报错长这样:
nginx: [emerg] bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions)
两个错误码指向的不是同一件事:10048是端口真被别的进程占了,10013多半是权限不足,或者端口落在系统保留区间里。先判断属于哪一种。
找出是谁占的:netstat
netstat -ano | findstr :8080
输出五列:协议、本地地址、外部地址、状态、PID。找状态是LISTENING的那一行,行尾的数字就是进程号。
如果只能看到ESTABLISHED、没有LISTENING,说明端口根本没被监听,那是连接没释放干净,不是占用。
拿到PID之后查进程名:
tasklist /fi "PID eq 1234"
确认可以杀再杀:
taskkill /PID 1234 /F
按进程名杀一批是taskkill /IM java.exe /F,同名进程会被一锅端,生产机器上别顺手敲。
PowerShell里少敲两步
cmd里要查两次,PowerShell 5.1,能直接拿到连接对象:
Get-NetTCPConnection -LocalPort 8080 -State Listen
OwningProcess字段就是PID。把进程名和可执行文件路径一起打出来:
Get-Process -Id (Get-NetTCPConnection -LocalPort 8080 -State Listen).OwningProcess | Select-Object Id,ProcessName,Path
看清楚是什么东西之后直接停掉:
Stop-Process -Id (Get-NetTCPConnection -LocalPort 8080 -State Listen).OwningProcess -Force
Path那一列值得多看一眼,2026年碰到过一次8080被占,进程名是java.exe,路径指向的却是某个国产中间件的内嵌JRE,光看进程名判断不出该不该杀。OwningProcess返回多个值时Stop-Process会挨个停,跑着一堆同名服务的机器上别盲执行。
PID是4的情况
这一种最折腾人。netstat显示占用80端口的PID是4,tasklist查出来进程名是System,杀不掉也不能杀。PID 4是系统内核进程,真正占着端口的是它里面的http.sys驱动,IIS 10.0、SQL Server Reporting Services、Web Deploy、WinRM走的都是这一套。
看http.sys上注册了哪些东西:
netsh http show servicestate
输出里会列出请求队列和对应的注册进程,顺着这一节往下翻,能找到是哪个服务把80端口挂走了。
要临时腾出端口,在管理员命令行执行net stop http /y,它会把依赖这个服务的东西一起停掉,包括IIS和打印相关的几个,重启之后恢复。机器上跑着正式站点就别这么干,把占用方改成别的端口更稳。
到了PowerShell 7.4,同样得回到netsh,没有更省事的办法。这套命令从Windows Server 2008那会儿就是这么用的,截至2026年9月也没换过。
端口落在保留区间
报错是10013,netstat却查不到任何进程占用时,八成撞上了Windows保留的端口段。开过Hyper-V或者装过Docker的机器特别容易碰上,系统会随机预留一整段动态端口给容器网络用,重启一次换一批。
netsh interface ipv4 show excludedportrange protocol=tcp
输出那一排排"受管理排除端口"就是被划走的范围,端口落在里面就会报10013。两条路可走:换一个不在排除范围里的端口,或者把动态端口范围整体挪走:
netsh int ipv4 set dynamicport tcp start=49152 num=16384
改完需要重启才生效。实测在Windows 10 22H2和Windows Server 2022上都能解掉,Windows 11 24H2上偶尔还会预留回来,再重启一次基本消失。当初不知道这条命令的时候,一台机器上为了起8080折腾了大半天,最后发现是8064到8163这一整段被划走了。
TIME_WAIT满屏
netstat -ano | findstr TIME_WAIT
这种不算占用,是端口处于等待释放的状态,默认要等120秒。压测或者短时间大量短连接会把临时端口耗光,表现为新建连接失败。注册表HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下加一个DWORD值TcpTimedWaitDelay,取30到300之间,重启生效。改之前想清楚,调太低会出现四元组复用导致的串包。
确认端口到底通不通
Test-NetConnection -ComputerName 127.0.0.1 -Port 8080
TcpTestSucceeded显示True才说明端口真在监听。本机curl也一样能验:curl -v http://127.0.0.1:8080。之前碰过一次监听正常、外部却访问不通,查了半天是防火墙入站规则没放行,netstat那一层看不出任何异常。
端口排查就三步:netstat找PID、tasklist查是谁、确认能杀再taskkill。PID 4和保留端口段这两种特殊情况,前面三步会全部落空,直接跳到netsh那几条命令。