获取随机免费开放的端口进行测试

问题描述 投票:6回答:2

我正在用REST API服务运行一些集成测试。问题是有时在下一次测试开始时,硬编码的端口并不空闲。因为它已经被之前的测试打开了,但还没有被系统关闭。

我使用的是OWIN,在下一次测试开始的那一刻,应用程序就会被关闭。

请您给我一个好的方法来确定系统的空闲端口。不经意间 然后关闭它?或者说这是不可能的。

因为它可能还没有被系统释放,就像已经发生的一样。

c# .net windows networking owin
2个回答
7
投票

作为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);

2
投票

要获得一个免费的端口

static int FreePort()
{
  TcpListener l = new TcpListener(IPAddress.Loopback, 0);
  l.Start();
  int port = ((IPEndPoint)l.LocalEndpoint).Port;
  l.Stop();
  return port;
}
© www.soinside.com 2019 - 2024. All rights reserved.