【问题标题】:Prevent Kestrel From Crashing When Port Is In Use防止 Kestrel 在端口使用时崩溃
【发布时间】:2019-10-29 15:22:31
【问题描述】:

我怀疑这是我正在尝试做的“奇怪”事情,但是...我已将 Kestrel 配置为侦听多个端口。问题是,有时,其中一个端口已在使用中。

这目前导致我的应用程序崩溃。

我希望看到的行为是它侦听我指定的所有可用端口。但我无法找到有关该主题的任何示例/文档。

例如,我可以将其配置为侦听 90、91、92、93...但如果端口 91 已在使用中,我希望它仅侦听端口 90、92、93。我不介意它是否引发异常或记录错误,只要我可以让它继续。我想避免“先检查”然后更改配置,因为这感觉就像等待发生的竞争条件)

谁能告诉我如何让 Kestrel 仅在可用端口上启动?

【问题讨论】:

    标签: asp.net-core .net-core kestrel-http-server


    【解决方案1】:

    你可以使用port 0;这样,Kestrel 在运行时动态绑定到可用端口,如 here 所说:

    private static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseUrls("http://*:0");
    

    此外,您可以像这样确定 Kestrel 在运行时实际绑定的端口:

    public static void Main(string[] args)
    {
        IWebHost webHost = CreateWebHostBuilder(args).Build();
    
        webHost.Start();
    
        string address = webHost.ServerFeatures
            .Get<IServerAddressesFeature>()
            .Addresses
            .First();
    
        int port = int.Parse(address.Split(':')[4]);
    }
    

    更新:

    如果指定的端口没有被其他应用程序使用,您可以检查端口可用性并启动项目:

    private static string[] GenerateUrls(IEnumerable<int> ports)
    {
        return ports.Select(port => $"http://localhost:{port}").ToArray();
    }
    
    private static IEnumerable<int> GetAvailablePorts(IEnumerable<int> ports)
    {
        IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
        IPEndPoint[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();
    
        IEnumerable<int> allActivePorts = tcpConnInfoArray.Select(endpoint => endpoint.Port).ToList();
    
        return ports.Where(port => !allActivePorts.Contains(port)).ToList();
    }
    

    最终的结果会是这样的:

    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }
    
    private static IWebHostBuilder CreateWebHostBuilder(string[] args)
    {
        IWebHostBuilder webHost = WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
    
        int[] ports = { 5000, 5050, 8585 };
    
        IEnumerable<int> availablePorts = GetAvailablePorts(ports).ToList();
        if (!availablePorts.Any())
            throw new InvalidOperationException("There are no active ports available to start the project.");
    
        webHost.UseUrls(GenerateUrls(availablePorts));
    
        return webHost;
    }
    

    【讨论】:

    • 我很欣赏这个答案,使用端口 0 听起来在很多情况下都会有所帮助;但我需要它在多个特定端口上启动。如果那有意义的话。我试图编辑问题并使其更清楚。我想给它一个端口列表 {20,21,22} 并让它监听这三个可用的端口。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 2018-12-26
    • 2013-05-30
    • 2022-01-19
    • 1970-01-01
    相关资源
    最近更新 更多