Предотвратить сбой Kestrel при использовании порта - PullRequest
3 голосов
/ 15 июня 2019

Я подозреваю, что это «странная» вещь, которую я пытаюсь сделать, но ... Я настроил Kestrel для прослушивания нескольких портов.Дело в том, что иногда один из этих портов уже используется.

В настоящее время это вызывает сбой моего приложения.

Поведение, которое я хотел бы видеть, заключается в том, что он прослушиваетвсе доступные порты, которые я указал.Но я не смог найти никаких примеров / документации по этой теме.

Например, я мог бы настроить его на прослушивание 90, 91, 92, 93 ... но если порт 91 уже подключениспользуйте, я хочу, чтобы он прослушивал только порты 90, 92, 93. Я не против, если он выдает исключение или регистрирует ошибку, если я могу продолжить его.Я хотел бы не «проверять сначала», а затем изменять конфигурацию, поскольку это похоже на состояние гонки, ожидающее наступления)

Может кто-нибудь сказать мне, как разрешить Kestrel запускаться только на доступных портах?

1 Ответ

2 голосов
/ 15 июня 2019

Вы можете использовать порт 0 ;при этом Kestrel динамически связывается с доступным портом во время выполнения, как сказано здесь :

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;
}
...