Skip to content

Instantly share code, notes, and snippets.

@epetrie
Created May 11, 2012 16:34
Show Gist options
  • Save epetrie/2660809 to your computer and use it in GitHub Desktop.
Save epetrie/2660809 to your computer and use it in GitHub Desktop.
misc network
/// <summary>
/// Gets the next available open port for use with RTP Video Streams. Range is evenly numbered UDP ports between 9000 and 9999.
/// </summary>
/// <param name="localAddress">The local address.</param>
/// <returns></returns>
public static int GetOpenPort(IPAddress localAddress)
{
return GetOpenPort(localAddress, 9000, 9999, 2, true, true);
}
/// <summary>
/// Gets the nearest open port (or port + range).
/// </summary>
/// <param name="localAddress">The local address.</param>
/// <param name="startingPort">The starting port.</param>
/// <param name="endingPort">The ending port.</param>
/// <param name="range">The range.</param>
/// <param name="requireEvenBasePort">if set to <c>true</c> [require even base port].</param>
/// <param name="udp">if set to <c>true</c> [UDP].</param>
/// <returns></returns>
public static int GetOpenPort(IPAddress localAddress, int startingPort, int endingPort, int range, bool requireEvenBasePort, bool udp)
{
// This will work fine in most cases, but there is no guarantee that a port obtained here will be open at the time that
// you attempt to use it. This should suffice for our purposes here, but a more robust implementation is advised for production applications.
// best practice here is to make sure we use the ports obtained through this method before allowing it to be called again.
ArgHelper.AssertThat(range >= 1);
ArgHelper.AssertThat(endingPort <= 65535);
if (requireEvenBasePort)
ArgHelper.AssertThat(startingPort % 2 == 0);
var additionalPorts = range - 1;
var validUsedPorts = new List<int>(
(
from endPoint in (udp ? IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners() : IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners())
where ((endPoint.Address == localAddress) && (endPoint.Port >= startingPort) && (endPoint.Port + additionalPorts <= endingPort))
select endPoint.Port
));
if (validUsedPorts.Count == 0)
return startingPort;
validUsedPorts.Sort();
for (var i = startingPort; i <= endingPort - additionalPorts; i++)
{
//skip odd base ports if needed.
if (requireEvenBasePort && i % 2 != 0)
continue;
//skip the rest if the port is in use.
if (validUsedPorts.Contains(i))
continue;
//return current port if no range was defined.
if (additionalPorts == 0)
return i;
var isUsed = false;
//test to see if the requested range is available
for (var j = i + 1; j <= i + additionalPorts; j++)
{
if (!validUsedPorts.Contains(j))
continue;
isUsed = true;
i = j;
}
if (isUsed)
continue;
return i;
}
return 0; //socket creation with port 0 will find any port available outside our range.
}
/// <summary>
/// Gets the local ip that the system will use for a connection to the specified remote IP Address.
///
/// Use this to automate RTP Sendback Url definition.
/// </summary>
/// <param name="remoteIpAddress">The remote ip address.</param>
/// <returns></returns>
public static IPAddress GetLocalIpAddressUsedFor(IPAddress remoteIpAddress)
{
using (var udpClient = new UdpClient())
{
udpClient.Connect(remoteIpAddress, 1);
return ((IPEndPoint)udpClient.Client.LocalEndPoint).Address;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment