Find the next TCP port in .NET

Viewed 47224

I want to create a new net.tcp://localhost:x/Service endpoint for a WCF service call, with a dynamically assigned new open TCP port.

I know that TcpClient will assign a new client side port when I open a connection to a given server.

Is there a simple way to find the next open TCP port in .NET?

I need the actual number, so that I can build the string above. 0 does not work, since I need to pass that string to another process, so that I can call back on that new channel.

8 Answers

Here is what I was looking for:

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

Use a port number of 0. The TCP stack will allocate the next free one.

I found the following code from Selenium.WebDriver DLL

Namespace: OpenQA.Selenium.Internal

Class: 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;
}

First open the port, then give the correct port number to the other process.

Otherwise it is still possible that some other process opens the port first and you still have a different one.

Here's a more abbreviated way to implement this if you want to find the next available TCP port within a given range:

private int GetNextUnusedPort(int min, int max)
{
    if (max < min)
        throw new ArgumentException("Max cannot be less than min.");

    var ipProperties = IPGlobalProperties.GetIPGlobalProperties();

    var usedPorts =
        ipProperties.GetActiveTcpConnections()
            .Where(connection => connection.State != TcpState.Closed)
            .Select(connection => connection.LocalEndPoint)
            .Concat(ipProperties.GetActiveTcpListeners())
            .Concat(ipProperties.GetActiveUdpListeners())
            .Select(endpoint => endpoint.Port)
            .ToArray();

    var firstUnused =
        Enumerable.Range(min, max - min)
            .Where(port => !usedPorts.Contains(port))
            .Select(port => new int?(port))
            .FirstOrDefault();

    if (!firstUnused.HasValue)
        throw new Exception($"All local TCP ports between {min} and {max} are currently in use.");

    return firstUnused.Value;
}
Related