防止使用端口时红est崩溃

时间:2019-06-15 04:57:44

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

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

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

我想看到的行为是,它监听我指定的所有可用端口。但是我找不到关于该主题的任何示例/文档。

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

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

1 个答案:

答案 0 :(得分:2)

您可以使用端口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;
}