Find the Next Tcp Port in .Net

Find the next TCP port in .NET

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

Thread-safe way to find the next TCP port in .NET (over multiple processes)

How can I build a utility to get a free TCP port from parallel running processes, without running into race conditions?

You can't. The idea of using some temporarily "free" port is wrong from start since what is actually free can change from one moment to the other on a system with multiple processes - no matter if your application itself uses threads or not. Thus, even if you've found some port which is free now it might have been used by another process before you've managed to bind to it.

The proper way is not to find a free port and then bind to it. The proper way is instead to bind your listener to port 0 and then determine which port was actually used. Then use this already created listener socket directly instead of closing it and trying to use the port it used for some new socket.

Get random free opened port for tests

As an alternative to TempoClick's answer, we can use the IPGlobalProperties.GetActiveTcpListeners() method to test if a port is available - without trying to open it in advance. GetActiveTcpListeners() returns all active TCP listeners on the system, and so we can use it to determine if a port is free or not.

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);
}

Note that GetActiveTcpListeners() doesn't return listening UDP endpoints, but we can get them with GetActiveUdpListeners().

So, you can start with the default port (or select a random value) and keep incrementing until you find a free port with the IsFree method.

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

A simple test:

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

A different approach is to use port zero. In this case, the system will select a random free port from the dynamic port range. We can get the number ot this port from the LocalEndpoint property.

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

In C#, how to check if a TCP port is available?

Since you're using a TcpClient, that means you're checking open TCP ports. There are lots of good objects available in the System.Net.NetworkInformation namespace.

Use the IPGlobalProperties object to get to an array of TcpConnectionInformation objects, which you can then interrogate about endpoint IP and port.


 int port = 456; //<--- This is your value
bool isAvailable = true;

// Evaluate current system tcp connections. This is the same information provided
// by the netstat command line application, just in .Net strongly-typed object
// form. We will look through the list, and if our port we would like to use
// in our TcpClient is occupied, we will set isAvailable to false.
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();

foreach (TcpConnectionInformation tcpi in tcpConnInfoArray)
{
if (tcpi.LocalEndPoint.Port==port)
{
isAvailable = false;
break;
}
}

// At this point, if isAvailable is true, we can proceed accordingly.

C#: How to find an available port in a range of specific ports in TCP?

I found a way to perform that:

private static int initialPort = 6001; // initial port to search from

public static void StartServerTCP()
{
bool serverSet = false;
while (!serverSet && initialPort <= 7000)
{
try
{
Console.WriteLine(Dns.GetHostName() + ": (Server:TCP) Trying to setup server at port: {0} [TCP]", initialPort);

serverSocket.Bind(new IPEndPoint(GetIP(), initialPort));
serverSocket.Listen(0);
serverSocket.BeginAccept(AcceptCallback, null);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(Dns.GetHostName() + ": (Server:TCP) Server setup completed at port {0} [TCP]\n", initialPort);
Console.ForegroundColor = ConsoleColor.Gray;
serverSet = true;
}
catch (Exception)
{
Console.WriteLine("\n" + Dns.GetHostName() + ": (Server:TCP) Port <{0}> is busy, trying a different one\n", initialPort);
initialPort++;
}
}
}

how do i find an available port before bind the socket with the endpoint?

If the port number doesn't matter you could pass 0 for the port to the IPEndPoint. In this case
the operating system (TCP/IP stack) assigns a free port number for you.

Socket sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
sock.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.1"), 0)); // Pass 0 here.

Console.Out.WriteLine("Assigned port: {0}",
((IPEndPoint)sock.LocalEndPoint).Port);

As @GrokSrc pointed out in the comments section you should of course dispose the socket when you're done with the socket by using the Dispose() method or the using statement.



Related Topics



Leave a reply



Submit