在.Net中查找下一个TCP端口

The*_*ker 62 .net c# wcf networking tcp

我想为WCF服务调用创建一个新的net.tcp:// localhost:x/Service端点,并使用动态分配的新的open tcp端口.

我知道当我打开与给定服务器的连接时,TcpClient将分配一个新的客户端端口.

有没有一种简单的方法可以在.Net中找到下一个打开的TCP端口?

我需要实际的数字,以便我可以构建上面的字符串,0不起作用,因为我需要将该字符串传递给另一个进程,以便我可以回调该新的通道.

The*_*ker 119

这是我在寻找的东西:

static int FreeTcpPort()
{
  TcpListener l = new TcpListener(IPAddress.Loopback, 0);
  l.Start();
  int port = ((IPEndPoint)l.LocalEndpoint).Port;
  l.Stop();
  return port;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果另一个进程在重新打开之前打开该端口会发生什么? (11认同)
  • 我成功地使用这种技术获得了一个免费端口.我也担心竞争条件,其他一些进程潜入并抓住最近被发现的自由端口.所以我在`var port = FreeTcpPort()`之间用强制`Sleep(100)`编写了一个测试,并在自由端口上启动了一个HttpListener.然后我在循环中运行了8个相同的过程.我永远不会遇到比赛的情况.我的轶事证据(Win 7)是操作系统显然是在短暂的端口(几千个)之间循环再次出现之前.所以上面的片段应该没问题. (10认同)
  • 然后你会得到一个错误,但这不是我的上下文的问题. (5认同)
  • 如果我理解这是如何正常工作的,你不能这样做:`TcpListener myActualServer = new TcpListener(ipAddress,0); myActualServer.Start(); return((IPEndPoint)myActualServer.LocalEndpoint).Port;`或者OP在实际启动监听器之前获取端口是否重要? (3认同)

Jer*_*rub 20

使用端口号0. TCP堆栈将分配下一个空闲的堆栈.

  • 这不起作用,因为我需要实际的#,而不仅仅是0.我需要数字来构建一个字符串. (3认同)

Fat*_*TAN 11

我从Selenium.WebDriver DLL 中找到了以下代码

命名空间:OpenQA.Selenium.Internal

: PortUtility

public static int FindFreePort()
{
    int port = 0;
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    try
    {
        IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 0);
        socket.Bind(localEP);
        localEP = (IPEndPoint)socket.LocalEndPoint;
        port = localEP.Port;
    }
    finally
    {
        socket.Close();
    }
    return port;
}
Run Code Online (Sandbox Code Playgroud)


jan*_*rgh 9

首先打开端口,然后将正确的端口号提供给另一个进程.

否则,某些其他进程仍然可能首先打开端口,但您仍然有另一个进程.

  • 您是否有代码示例来尽可能轻松地获得这样的 tcp 端口? (2认同)

Eri*_*dil 8

该解决方案可与TheSeeker的公认答案相媲美。虽然我认为它更具可读性:

using System;
using System.Net;
using System.Net.Sockets;

    private static readonly IPEndPoint DefaultLoopbackEndpoint = new IPEndPoint(IPAddress.Loopback, port: 0);

    public static int GetAvailablePort()
    {
        using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        {
            socket.Bind(DefaultLoopbackEndpoint);
            return ((IPEndPoint)socket.LocalEndPoint).Port;
        }
    }
Run Code Online (Sandbox Code Playgroud)


zum*_*ard 6

如果您只想提供一个起始端口,并让它返回下一个可用的TCP端口,请使用如下代码:

public static int GetAvailablePort(int startingPort)
{
    var portArray = new List<int>();

    var properties = IPGlobalProperties.GetIPGlobalProperties();

    // Ignore active connections
    var connections = properties.GetActiveTcpConnections();
    portArray.AddRange(from n in connections
                        where n.LocalEndPoint.Port >= startingPort
                        select n.LocalEndPoint.Port);

    // Ignore active tcp listners
    var endPoints = properties.GetActiveTcpListeners();
    portArray.AddRange(from n in endPoints
                        where n.Port >= startingPort
                        select n.Port);

    // Ignore active UDP listeners
    endPoints = properties.GetActiveUdpListeners();
    portArray.AddRange(from n in endPoints
                        where n.Port >= startingPort
                        select n.Port);

    portArray.Sort();

    for (var i = startingPort; i < UInt16.MaxValue; i++)
        if (!portArray.Contains(i))
            return i;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)