前陣子我的 Windows 10 (版本 1809) 電腦發生了一個靈異事件,就是電腦突然無法 LISTEN 常用的 4200 與 3000 通訊埠,我想盡腦汁也想不出為什麼無法 LISTEN,超出了我的認知範圍,雖然最後已經找到解決辦法,但還是有些疑惑尚未釐清。我就用這篇文章整理一下我遭遇的狀況!
問題說明
我常用的 Angular CLI 會在啟動開發伺服器時使用 4200 Port,而 lite-server 則預設採用 3000 Port,以及 .NET Core CLI 則是 5000 與 5001 Port,這幾年來從來也沒有出問題過,但就某一天,有個 Port 3000 不能用了,嘗試重開機後,變成 Port 4200 不能用了,實在超詭異 !
由於我當時不能用的通訊埠是 Port 3000,以下是我的偵查過程:
-
先用 netstat -nat | findstr 3000
查出 Port 3000 的使用情形
從上圖可以看出我的電腦沒有任何應用程式正在使用 Port 3000 通訊埠,但就是被不明原因占用,不知道是被誰用掉的。
-
使用 TCPView 查看通訊埠使用情況
這裡一樣沒有任何使用 Port 3000 的任何應用程式。
-
開啟資源監視器查看所有接聽連接埠
一樣沒有任何使用 Port 3000 的活動!
-
使用 CurrPorts 查看通訊埠使用情況
一樣沒有任何使用 Port 3000 的活動!
照理來說 netstat
已經足以看出電腦的網路連線狀況,但這實在超出我能理解的範圍,總之沒有應用程式正在使用 Port 3000,怎麼這個 Port 就是無法使用呢?我還換了各種不同的工具嘗試去 LISTEN 3000 Port 也都失敗,像是:
-
netcat
nc -L -p 3000
Can't grab 0.0.0.0:3417 with bind
-
live-server
live-server --port=3000
Error: listen EACCES 0.0.0.0:3417
-
.NET Core CLI
SET ASPNETCORE_URLS=https://*:3000 && dotnet run --no-launch-profile
crit: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to start Kestrel.
System.Net.Sockets.SocketException (10013): 嘗試存取通訊端被拒絕,因為存取權限不足。
追查過程
這些工具通通遇到無法 LISTEN 的錯誤,所以我最後就直接推斷,應該是作業系統造成的!
我從 Port are blocked after you install February 13 cumulative update 4074588 in Windows 10 Version 1709 這篇文章找到一點蛛絲馬跡,發現了以下命令,這個命令可以列出所有被作業系統排除的通訊埠(Ports)清單:
netsh int ipv4 show excludedportrange protocol=tcp
這才發現原來我的 Port 3000 不能用,是因為我這台電腦的 Port 2990 ~ 3089 都被不明原因給排除使用範圍,但是被哪個應用程式或系統服務保留卻不得而知,網路上完全沒有文件提到怎樣進一步追查。
最為詭異的地方在於,每次重開機後,有某些範圍的通訊埠會有變化,所以可能這次不能用 3000 Port,重開機後可能變成另一個範圍不能用,完全摸不著頭緒。
然後我試著將 Hyper-V 關閉,也試著將 Docker Desktop 移除,這些保留通訊埠確實少了一點,但每次重開機後,變動的保留通訊埠還是不斷的在 1541 ~ 10000 之間跳動,讓人覺得非常不安。
dism.exe /Online /Disable-Feature:Microsoft-Hyper-V
解決方案
在進一步研究後發現,其實有兩種解決方法:
-
重啟 winnat
服務即可釋放所有被鎖定的 Port Range
# 1. 停用 WSL 服務
wsl --shutdown
wsl -l -v
# 2. 停用 Docker 服務
# 3. 重啟 WinNAT 服務
net stop winnat
net start winnat
# 4. 啟動 Docker 服務
# 5. 如果發現網路出現問題,那還是用「重開治百病」這招吧!
參考來源: https://superuser.com/a/1610009 & https://github.com/docker/for-win/issues/3171#issuecomment-739740248
-
設定自己專用的保留通訊埠
原來 Windows 10 使用者可以設定自己專用的保留通訊埠,所以我決定把常用的通訊埠固定下來,這樣就沒有人可以用我會用到的通訊埠了!
netsh int ipv4 add excludedportrange protocol=tcp numberofports=1 startport=3000
netsh int ipv4 add excludedportrange protocol=tcp numberofports=1 startport=3001
netsh int ipv4 add excludedportrange protocol=tcp numberofports=1 startport=4200
netsh int ipv4 add excludedportrange protocol=tcp numberofports=1 startport=5000
netsh int ipv4 add excludedportrange protocol=tcp numberofports=1 startport=5001
netsh int ipv4 add excludedportrange protocol=tcp numberofports=1 startport=8080
netsh int ipv4 add excludedportrange protocol=tcp numberofports=1 startport=8888
如果要刪除自訂的保留通訊埠,可以用以下命令:
netsh int ipv4 delete excludedportrange protocol=tcp numberofports=1 startport=3000
netsh int ipv4 delete excludedportrange protocol=tcp numberofports=1 startport=3001
netsh int ipv4 delete excludedportrange protocol=tcp numberofports=1 startport=4200
netsh int ipv4 delete excludedportrange protocol=tcp numberofports=1 startport=5000
netsh int ipv4 delete excludedportrange protocol=tcp numberofports=1 startport=5001
netsh int ipv4 delete excludedportrange protocol=tcp numberofports=1 startport=8080
netsh int ipv4 delete excludedportrange protocol=tcp numberofports=1 startport=8888
相關連結
- Hyper-V related
- Docker related
- Windows
- Others