Al final de esta respuesta, encontrará una implementación completa de una estructura para representar una dirección IPV4.
aquí es realmente sencillo ejemplo de utilización: -
List<IPV4Address> list = new List<IPV4Address>();
list.Add(IPV4Address.FromString("3.4.0.0", 24));
var x = IPV4Address.FromString("3.4.0.6");
foreach (var addr in list.Where(a => a.Contains(x)))
Console.WriteLine(addr);
El valor "3.4.0.0/255.255.255.0" se muestra enla consola desde 3.4.0.6 se encuentra en la subred 3.4.0.0/24. Suponiendo list
está lleno de diferentes subredes y x
podría contener cualquier dirección, entonces esto: -
var result = list.Where(a => a.Contains(x))
.OrderByDescending(a => a.Mask)
.FirstOrDefault();
seleccionará la subred más específica para que contiene x
.
public struct IPV4Address
{
private UInt32 _Value;
private UInt32 _Mask;
public UInt32 Value
{
get { return _Value; }
private set { _Value = value; }
}
public UInt32 Mask
{
get { return _Mask; }
private set { _Mask = value; }
}
public static IPV4Address FromString(string address)
{
return FromString(address, 32);
}
public static IPV4Address FromString(string address, int maskLength)
{
string[] parts = address.Split('.');
UInt32 value = ((UInt32.Parse(parts[0]) << 24) +
((UInt32.Parse(parts[1])) << 16) +
((UInt32.Parse(parts[2])) << 8) +
UInt32.Parse(parts[3]));
return new IPV4Address(value, maskLength);
}
public IPV4Address(UInt32 value)
{
_Value = value;
_Mask = int.MaxValue;
}
public IPV4Address(UInt32 value, int maskLength)
{
if (maskLength < 0 || maskLength > 32)
throw new ArgumentOutOfRangeException("maskLength", "Must be 0 to 32");
_Value = value;
if (maskLength == 32)
_Mask = UInt32.MaxValue;
else
_Mask = ~(UInt32)((1 << (32 - maskLength))-1);
if ((_Value & _Mask) != _Value)
throw new ArgumentException("Address value must be contained in mask");
}
public bool Contains(IPV4Address address)
{
if ((Mask & address.Mask) == Mask)
{
return (address.Value & Mask) == Value;
}
return false;
}
public override string ToString()
{
string result = String.Format("{0}.{1}.{2}.{3}", (_Value >> 24),
(_Value >> 16) & 0xFF,
(_Value >> 8) & 0xFF,
_Value & 0xFF);
if (_Mask != UInt32.MaxValue)
result += "/" + String.Format("{0}.{1}.{2}.{3}", (_Mask >> 24),
(_Mask >> 16) & 0xFF,
(_Mask >> 8) & 0xFF,
_Mask & 0xFF);
return result;
}
}
+1, ¿Pero no debería el constructor de ipawpl usar una longitud de prefijo de 32? Idealmente, una instancia construida con IPAddressWithPrefixLength (IPAddress.Parse ("3.4.5.6"), 32) también debería encontrarse, ¿no? –
@Vinay: No lo creo, porque la longitud del prefijo en 3.4.5.6 sigue siendo de 16 bits, ¿no? (¿o 24?) – dtb
@dtb: Lo que quise decir es que la dirección de red (con el prefijo de 16 bits) debe coincidir con una dirección arbitraria en la subred (que podría ser una dirección completa de 32 bits, o decir una de 24 bits subred de la red 3.4.0.0 original). –