获取随机打开的端口进行测试

cas*_*rad 5 .net c# windows networking owin

我正在使用REST API服务运行一些集成测试.
问题是,有时硬编码端口在下次测试开始时不是空闲的.因为它是由先前的测试打开的,并且尚未被系统关闭.

我使用OWIN,应用程序在下一次测试开始时关闭.

你能否建议我一个很好的方法来确定系统上的自由端口,而无需提前打开并关闭它?或者说这是不可能的.

因为系统尚未释放它,就像它已经发生的那样.

t.m*_*dam 8

作为 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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,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;
}
Run Code Online (Sandbox Code Playgroud)

一个简单的测试:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用端口零。在这种情况下,系统将从动态端口范围中随机选择一个空闲端口。我们可以从LocalEndpoint属性中获取此端口的编号。

TcpListener server = new TcpListener(IPAddress.Loopback, 0);
server.Start();
int port = ((IPEndPoint)server.LocalEndpoint).Port;
Console.WriteLine(port);
Run Code Online (Sandbox Code Playgroud)