public static ushort GetAvailablePort(ushort RangeStart = 1025, ushort RangeEnd = ushort.MaxValue, IPAddress BindIp = null, bool IncludeIdlePorts = false)
{
if (BindIp == null) BindIp = IPAddress.Parse("127.0.0.1");
var IpProperties = IPGlobalProperties.GetIPGlobalProperties();
// If the ip we want a port on is an 'any' or loopback port we need to exclude all ports that are active on any IP
Func<IPAddress, bool> IsIpAnyOrLoopBack = (Ip) =>
{
return
IPAddress.Any.Equals(Ip) ||
IPAddress.IPv6Any.Equals(Ip) ||
IPAddress.Loopback.Equals(Ip) ||
IPAddress.IPv6Loopback.
Equals(Ip)
;
};
// Get all active ports on specified IP.
var ExcludedPorts = new List<ushort>();
// If a port is open on an 'any' or 'loopback' interface then include it in the excludedPorts
ExcludedPorts.AddRange(
from n in IpProperties.GetActiveTcpConnections()
where
n.LocalEndPoint.Port >= RangeStart
&& n.LocalEndPoint.Port <= RangeEnd
&&
(
IsIpAnyOrLoopBack(BindIp) ||
n.LocalEndPoint.Address.Equals(BindIp) ||
IsIpAnyOrLoopBack(n.LocalEndPoint.Address)
)
&& (!IncludeIdlePorts || n.State != TcpState.TimeWait)
select (ushort)n.LocalEndPoint.Port
);
ExcludedPorts.AddRange(
from n in IpProperties.GetActiveTcpListeners()
where
n.Port >= RangeStart && n.Port <= RangeEnd
&&
(IsIpAnyOrLoopBack(BindIp) || n.Address.Equals(BindIp) || IsIpAnyOrLoopBack(n.Address))
select (ushort)n.Port
);
ExcludedPorts.AddRange(
from n in IpProperties.GetActiveUdpListeners()
where
n.Port >= RangeStart && n.Port <= RangeEnd
&&
(IsIpAnyOrLoopBack(BindIp) || n.Address.Equals(BindIp) || IsIpAnyOrLoopBack(n.Address))
select (ushort)n.Port
);
ExcludedPorts.Sort();
for (ushort Port = RangeStart; Port <= RangeEnd; Port++)
{
if (!ExcludedPorts.Contains(Port))
{
return Port;
}
}
return 0;
}