Note that you can find a similar question here: Find the next TCP port in .NET
My problem is that the solution (accepted answer) of this question is not thread-safe: Find the next TCP port in .NET - Top answer
static int FreeTcpPort()
{
TcpListener l = new TcpListener(IPAddress.Loopback, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
return port;
}
I wrote a test which proves that:
private readonly BlockingCollection<int> _freePorts = new BlockingCollection<int>();
[Test]
public void FreeTcpPort_ShouldBeThreadSafe()
{
// Act
Parallel.For(0, 10000,
index =>
{
int freeTcpPort = FreeTcpPort();
_freePorts.Add(freeTcpPort);
Console.WriteLine(freeTcpPort);
} );
var query = _freePorts.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => new { Element = y.Key, Counter = y.Count() })
.ToList();
// Assert
Assert.That(query.All(x => x.Counter == 1), () => query.First(x => x.Counter > 1).ToString());
}
The test above is flaky. On my machine it fails more then 50% of the times I run it. Here is a part of the console output of a failing test:
51470
51472
51473
51365
51475
51367
51366
51474
51475
51476
51478
51479
51480
The problem is that port 51475 in this case is returned twice. Note that the same port is returned from 2 parallel running threads and not because it cycles through the port range and get an overlap (which happens with a higher loop count).
Note that it is not enough to just add a lock statement for my use case, because I use this dynamic ports for parallel running system tests, which run in separate processes. Therefore I am searching for a solution which always returns a unique and free TCP port also for parallel running process.
How can I build a utility to get a free TCP port from parallel running processes, without running into race conditions?