Получить случайный открытый порт для тестов - PullRequest
0 голосов
/ 17 декабря 2018

Я провожу некоторые интеграционные тесты со службой REST API.
Проблема в том, что иногда жестко заданный порт не свободен в момент запуска теста в следующий раз.Поскольку он был открыт предыдущим тестом и еще не закрыт системой.

Я использую OWIN, приложение закрывается в момент запуска следующего теста.

Не могли бы вы предложитьмне хороший способ определить свободный порт в системе , не открывая его заранее , а затем закрывая его?Или скажите, что это невозможно.

Поскольку система еще не освободила его, как это уже происходит.

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

В качестве альтернативы ответа TempoClick , мы можем использовать метод IPGlobalProperties.GetActiveTcpListeners(), чтобы проверить, доступен ли порт - не пытаясь открыть его заранее.GetActiveTcpListeners() возвращает всех активных прослушивателей TCP в системе, поэтому мы можем использовать его, чтобы определить, свободен порт или нет.

public bool IsFree(int port)
{
    IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
    IPEndPoint[] listeners = properties.GetActiveTcpListeners();
    int[] openPorts = listeners.Select(item => item.Port).ToArray<int>();
    return openPorts.All(openPort => openPort != port);
}

Обратите внимание, что GetActiveTcpListeners() не возвращает прослушиваемые конечные точки UDP, но мы можем получить их с помощью GetActiveUdpListeners().

Итак, вы можете начать с порта по умолчанию (или выбрать случайное значение) и продолжать увеличивать его, пока не найдете свободный порт с помощью метода IsFree.

int NextFreePort(int port = 0) 
{
    port = (port > 0) ? port : new Random().Next(1, 65535);
    while (!IsFree(port)) 
    {
        port += 1;
    }
    return port;
}

Простой тест:

using System;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Linq;

class Test
{
    static void Main(string[] args)
    {
        int port = 1000;
        Console.WriteLine(IsFree(port));
        TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), port);
        server.Start();   
        Console.WriteLine(IsFree(port));
        Console.WriteLine(NextFreePort(port));
    }

    static bool IsFree(int port)
    {
        IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
        IPEndPoint[] listeners = properties.GetActiveTcpListeners();
        int[] openPorts = listeners.Select(item => item.Port).ToArray<int>();
        return openPorts.All(openPort => openPort != port);
    }

    static int NextFreePort(int port = 0) {
        port = (port > 0) ? port : new Random().Next(1, 65535);
        while (!IsFree(port)) {
            port += 1;
        }
        return port;
    }
}

Другой подход заключается в использовании нулевого порта.В этом случае система выберет произвольно свободный порт из диапазона динамических портов.Мы можем получить номер этого порта из свойства LocalEndpoint.

TcpListener server = new TcpListener(IPAddress.Loopback, 0);
server.Start();
int port = ((IPEndPoint)server.LocalEndpoint).Port;
Console.WriteLine(port);
0 голосов
/ 17 декабря 2018

Для получения бесплатного порта

static int FreePort()
{
  TcpListener l = new TcpListener(IPAddress.Loopback, 0);
  l.Start();
  int port = ((IPEndPoint)l.LocalEndpoint).Port;
  l.Stop();
  return port;
}
...