修改久未維護 ASP.NET Core 專案,在 Visual Studio 2019 要用 Kestrel 偵錯時冒出以下錯誤:

info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using 'C:\Users\Jeffrey\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
      Unable to bind to http://localhost:50246 on the IPv4 loopback interface: 'An attempt was made to access a socket in a way forbidden by its access permissions'.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
      Unable to bind to http://localhost:50246 on the IPv6 loopback interface: 'An attempt was made to access a socket in a way forbidden by its access permissions'.
crit: Microsoft.AspNetCore.Server.Kestrel[0]
      Unable to start Kestrel.
System.IO.IOException: Failed to bind to address http://localhost:50246. ---> System.AggregateException: One or more errors occurred. (An attempt was made to access a socket in a way forbidden by its access permissions) (An attempt was made to access a socket in a way forbidden by its access permissions) ---> System.Net.Sockets.SocketException: An attempt was made to access a socket in a way forbidden by its access permissions
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)

嘗試以下解法,都沒能解決問題:

  1. 開權限 netsh http add urlacl url=http://+:50246/ user=JEFFWIN10\jeffrey 無效。(且印象中僅本機存取應不需要)
  2. 改用 Administrator 執行 Visual Studio 2019,一樣出現存取權被拒錯誤。
  3. 爬到一篇 SuperUser 討論有人遇到相似狀況但無解,
  4. 改用 IIS Express 偵測,則出現 Unable to connect to web server 'IIS Express'. 錯誤。

    並在 Log 檔看到以下訊息:(IIS Express 用 50245,與 Kestrel 不同)
    Failed to register URL "http://localhost:50245/" for site "Miniblog.Core" application "/". Error description: The process cannot access the file because it is being used by another process. (0x80070020)
    由此推測應與權限無關,而是 50245 Port 被佔用了。
  5. 執行 netstat -a 檢查沒看到有其他程序佔用 50245 或 50246 Port。
  6. 嘗試重開機無濟於事。
  7. 修改 Port 為 50247、50248、50348 結果相同。

一籌莫展之際,我將 Port 改成 50046,竟意外成功了。

再試了幾個 Port 發現似乎是特定範圍的 Port 有問題。於是我寫了一支程式下去掃瞄:

Bingo! 我抓出 50060-50459 這個區間的 Port 無法繫結:

用 50060、50459 關鍵字,爬到一篇 gRPC 討論,提到在 2018 二月 Windows 10 KB4074588 更新之後封鎖了一些 Port:

After installing this update, applications may not be able to reserve or bind to ports that previously worked.

netsh interface ipv4 show excludedportrange protocol=tcp 指令可查詢禁用範圍:

依查詢結果,49703-59902、50060-50459、50472-50571、50791-50890 都是禁區,有趣的是,我一開始測試成功的 50046 也列在 50000-50059 禁區,但是有加註 Administrated port exclusions 行為似與其他區段不同,不想深究,決定以後測試都用 60000 以上的 Port 就是了。

【心得】在 Windows 10 遇到 An attempt was made to access a socket in a way forbidden by its access permissions 或 Port 'xxxx' is already being used by another appicatoin 錯誤時,請優先查詢 netsh interface ipv4 show excludedportrange protocol=tcp,排除誤入 Port 保留範圍之可能。

[2019-11-25 更新] 感謝讀者 Steven Huang 補充,保哥也分享過相關問題 - Windows 10 無法 LISTEN Port 4200 與 Port 3000 的靈異事件整理,文末還有新增自訂保留區的做法。 (文章我應該也有看到,可惜沒留在腦海,這次沒省到時間,最終還是自己走過一遍,噗。)

Kestrel failed to start because of 'An attempt was made to access a socket in a way forbidden by its access permissions' error. After investigation, I found the reserved ports of Windows 10.


Comments

# by Cash

哈,之前有遇到 port 被 chrome 擋掉 https://superuser.com/questions/188058/which-ports-are-considered-unsafe-by-chrome

# by 卡比

遇到一定出事,謝分享

# by Steven Huang

保哥的文章也有寫到 port 被禁用的問題。 https://blog.miniasp.com/post/2019/03/31/Ports-blocked-by-Windows-10-for-unknown-reason 這篇文章最後有提供可以把自己常用的 port 保留下來的技巧。

# by Jeffrey

to Steven Huang, 感謝補充,已加入本文。文章我應該也有看到,可惜沒留在腦海,這次沒省到時間 Orz

# by Eric Wu

但下指令保留住特定 Port 後 自己的程式去使用也是會發生 "程序無法存取檔案,因為檔案正由另一個程序使用" 的錯誤 該怎麼解決?

# by Jeffrey

to Eric Wu, 看起來是不一樣的錯誤,會不會是網路連線部分的問題解決掉之後,變成後續的檔案存取部分出錯?

# by Eric Wu

To Jeffrey "程序無法存取檔案,因為檔案正由另一個程序使用" 的錯誤 應該就是你文中也有顯示的錯誤 . Error description: The process cannot access the file because it is being used by another process. (0x80070020) 就是那的保留的PORT無法開啟 目前問題就是因為不確定系統會保留哪些PORT 所以自己選定特定PORT保留後 自己的程式再開啟這個特定PORT就會出現這個錯誤 還不知道怎麼解決

# by Jeffrey

to Eric Wu, 我漏看 IIS Express 那段了(羞),有試過避開常被佔用的 Port 區段嗎?例如:使用 60000 以上或 30000 以下的 Port,若不管怎麼跳 Port 都會被咬住,可能另外有原因。

# by Eric Wu

To Jeffrey 我本來以為設定保留就是通知系統不再使用該Port 進而讓自己的程式可以安全使用 看來是想錯了 will 保哥那篇文有回說 "你的程式要用之前刪除自訂的保留通訊埠即可" 這樣每次使用完都還要再設定一次保留,有點麻煩

Post a comment