5

全世界只有我遇到?ASP.NET Core localhost 動態 Port 繫結錯誤

 1 year ago
source link: https://blog.darkthread.net/blog/no-dyna-port-to-localhost/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

全世界只有我遇到?ASP.NET Core localhost 動態 Port 繫結錯誤-黑暗執行緒

用 Visual Studio 建了一個 ASP.NET Core 專案跑不起來,試了用 dotnet new 新建也是如此,錯誤訊如下:

X:\MyTest\EmptyWeb>dotnet run
Building...
Unhandled exception. System.InvalidOperationException: Dynamic port binding is not supported when binding to localhost. You must either bind to 127.0.0.1:0 or [::1]:0, or both.
   at Microsoft.AspNetCore.Server.Kestrel.Core.LocalhostListenOptions..ctor(Int32 port)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.ParseAddress(String address, Boolean& https)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.AddressesStrategy.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(IEnumerable`1 listenOptions, AddressBindContext context, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
   at Microsoft.AspNetCore.Builder.WebApplication.Run(String url)
   at Program.<Main>$(String[] args) in X:\MyTest\EmptyWeb\Program.cs:line 6

Dynamic port binding is not supported when binding to localhost. You must either bind to 127.0.0.1:0 or [::1]:0, or both. 錯誤訊息無比明確,但 Google 結果只有一筆,還是 Github 某個 Kooboo.HttpServer 專案原始碼中的錯誤訊息定義:

Fig2_638004078907394347.png

第一次遇到這種詭異狀況,難道全世界只有我一個人遇到這個問題?

查詢 ASP.NET Core 原始碼,在 aspnetcore/src/Servers/Kestrel/Core/src/CoreStrings.resx 找到 DynamicPortOnLocalhostNotSupported 定義相同訊息的字串(筆記:所以 Google 不是所有公開連結都搜得到),再進一步追到內部物件 LocalhostListenOptions 會在傳入 localhost:0 時噴錯:

internal sealed class LocalhostListenOptions : ListenOptions
{
    internal LocalhostListenOptions(int port)
        : base(new IPEndPoint(IPAddress.Loopback, port))
    {
        if (port == 0)
        {
            throw new InvalidOperationException(CoreStrings.DynamicPortOnLocalhostNotSupported);
        }
    }
   //...略....

回頭檢查 EmptyWeb\Properties\launchSettings.json 果真出現 ℎttp://localhost:0! 比對正常專案應該要類似 "applicationUrl": "ℎttps://localhost:7238;ℎttp://localhost:5000",為什麼會出現 localhost:0 是個謎:

Fig1_638004078909345508.png

接著一陣胡亂操作,更新 Visual Studio 版本初試沒用,但再重開機問題便消失。由於無法重現錯誤,也就無法再調查,筆記備忘。

至於為什麼 localhost 不支援動態 Port,但 127.0.0.1、::1 可以?我猜測是因為 localhost 同時代表 127.0.0.1 跟 ::1,各自的可用 Port 不同,難以動態決定 Port (理論上還是可能,但複雜度較高)。在 AddressBinder.ParseAddress 有一段註解,就當成佐證吧:

        else if (string.Equals(parsedAddress.Host, "localhost", StringComparison.OrdinalIgnoreCase))
        {
            // "localhost" for both IPv4 and IPv6 can't be represented as an IPEndPoint.
            options = new LocalhostListenOptions(parsedAddress.Port);
        }

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK