Detecting the next available, free TCP port
.NET 3.5, C#
I recently had a need to find an available port for selenium, starting at the default of 4444. The code below checks to see if the port you're about to use is available, incrementing your port number to find the next free port if your first choice is in use.
This very simple method uses a global mutex to avoid a race condition when releasing a port.
Adapting it to use UDP is beyond what I need, but it'll be very easy to do - just replace ipGlobalProperties.GetActiveTcpListeners() with ipGlobalProperties.GetActiveUdpListeners();
/// <summary>
/// Provides static methods for operations
/// commonly required when working with TCP ports
/// </summary>
public static class TcpPort
{
private const string PortReleaseGuid =
"8875BD8E-4D5B-11DE-B2F4-691756D89593";
/// <summary>
/// Check if startPort is available, incrementing and
/// checking again if it's in use until a free port is found
/// </summary>
/// <param name="startPort">The first port to check</param>
/// <returns>The first available port</returns>
public static int FindNextAvailablePort(int startPort)
{
int port = startPort;
bool isAvailable = true;
var mutex = new Mutex(false,
string.Concat("Global/", PortReleaseGuid));
mutex.WaitOne();
try
{
IPGlobalProperties ipGlobalProperties =
IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] endPoints =
ipGlobalProperties.GetActiveTcpListeners();
do
{
if (!isAvailable)
{
port++;
isAvailable = true;
}
foreach (IPEndPoint endPoint in endPoints)
{
if (endPoint.Port != port) continue;
isAvailable = false;
break;
}
} while (!isAvailable && port < IPEndPoint.MaxPort);
if (!isAvailable)
throw new NoAvailablePortsInRangeException();
return port;
}
finally
{
mutex.ReleaseMutex();
}
}
}
For usage examples, please see my integration tests:
[TestFixture]
public class TcpPortFixture
{
[Test]
public void FindNextAvailablePort()
{
Assert.That(TcpPort.FindNextAvailablePort(4444),
Is.EqualTo(4444));
}
[Test]
public void FindNextAvailablePortInUse()
{
var tcpListener =
new TcpListener(IPAddress.Parse("127.0.0.1"), 4444);
try
{
tcpListener.Start();
Assert.That(TcpPort.FindNextAvailablePort(4444),
Is.EqualTo(4445));
}
finally
{
tcpListener.Stop();
}
}
}

