¿Cómo convertir una dirección IPv4 en un número entero en C #?

Estoy buscando una función que convierta una dirección IPv4 estándar en un Entero. Puntos de bonificación disponibles para una función que hará lo contrario.

La solución debe estar en C #.

Los enteros sin signo de 32 bits son direcciones IPv4. Mientras tanto, la propiedad IPAddress.Address , mientras está en desuso, es un Int64 que devuelve el valor sin signo de 32 bits de la dirección IPv4 (el problema es que está en el orden de bytes de la red, por lo que debe cambiarlo).

Por ejemplo, mi google.com local está en 64.233.187.99 . Eso es equivalente a:

 64*2^24 + 233*2^16 + 187*2^8 + 99 = 1089059683 

Y de hecho, http: // 1089059683 / funciona como se esperaba (al menos en Windows, probado con IE, Firefox y Chrome; sin embargo, no funciona en el iPhone).

Aquí hay un progtwig de prueba para mostrar ambas conversiones, incluido el intercambio de bytes de red / host:

 using System; using System.Net; class App { static long ToInt(string addr) { // careful of sign extension: convert to uint first; // unsigned NetworkToHostOrder ought to be provided. return (long) (uint) IPAddress.NetworkToHostOrder( (int) IPAddress.Parse(addr).Address); } static string ToAddr(long address) { return IPAddress.Parse(address.ToString()).ToString(); // This also works: // return new IPAddress((uint) IPAddress.HostToNetworkOrder( // (int) address)).ToString(); } static void Main() { Console.WriteLine(ToInt("64.233.187.99")); Console.WriteLine(ToAddr(1089059683)); } } 

@Barry Kelly y @Andrew Hare, en realidad, no creo que la multiplicación sea la forma más clara de hacer esto (todo correcto).

Una dirección IP “formateada” Int32 se puede ver como la siguiente estructura

 [StructLayout(LayoutKind.Sequential, Pack = 1)] struct IPv4Address { public Byte A; public Byte B; public Byte C; public Byte D; } // to actually cast it from or to an int32 I think you // need to reverse the fields due to little endian 

Entonces para convertir la dirección IP 64.233.187.99 podrías hacer:

 (64 = 0x40) << 24 == 0x40000000 (233 = 0xE9) << 16 == 0x00E90000 (187 = 0xBB) << 8 == 0x0000BB00 (99 = 0x63) == 0x00000063 ---------- =| 0x40E9BB63 

para que pueda sumrlos usando + o puede binairy o juntos. Resultando en 0x40E9BB63 que es 1089059683. (En mi opinión, mirando en hexadecimal es mucho más fácil ver los bytes)

Entonces podrías escribir la función como:

 int ipToInt(int first, int second, int third, int fourth) { return (first << 24) | (second << 16) | (third << 8) | (fourth); } 

Para convertir de IPv4 a un número entero correcto:

 IPAddress address = IPAddress.Parse("255.255.255.255"); byte[] bytes = address.GetAddressBytes(); Array.Reverse(bytes); // flip big-endian(network order) to little-endian uint intAddress = BitConverter.ToUInt32(bytes, 0); 

Y para convertir de nuevo:

 byte[] bytes = BitConverter.GetBytes(4294967295); Array.Reverse(bytes); // flip little-endian to big-endian(network order) string ipAddress = new IPAddress(bytes).ToString(); 

Explicación:

Las direcciones IP están en orden de red (big-endian), mientras que las int son little-endian en Windows, por lo que para obtener un valor correcto, debe invertir los bytes antes de convertir.

Además, incluso para IPv4 , un int no puede contener direcciones más grandes que 127.255.255.255 , por ejemplo, la dirección de difusión (255.255.255.255) , por lo tanto, utilice uint .

Prueba esto:

 private int IpToInt32(string ipAddress) { return BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes().Reverse().ToArray(), 0); } private string Int32ToIp(int ipAddress) { return new IPAddress(BitConverter.GetBytes(ipAddress).Reverse().ToArray()).ToString(); } 

Como nadie publicó el código que usa BitConverter y realmente verifica el endianness, aquí va:

 byte[] ip = address.Split('.').Select(s => Byte.Parse(s)).ToArray(); if (BitConverter.IsLittleEndian) { Array.Reverse(ip); } int num = BitConverter.ToInt32(ip, 0); 

y de vuelta:

 byte[] ip = BitConverter.GetBytes(num); if (BitConverter.IsLittleEndian) { Array.Reverse(ip); } string address = String.Join(".", ip.Select(n => n.ToString())); 

He encontrado algunos problemas con las soluciones descritas, al enfrentar Direcciones IP con un valor muy grande. El resultado sería que el byte [0] * 16777216 se desbordará y se convertirá en un valor int negativo. Lo que lo solucionó fue una operación de conversión de tipo simple.

 public static long ConvertIPToLong(string ipAddress) { System.Net.IPAddress ip; if (System.Net.IPAddress.TryParse(ipAddress, out ip)) { byte[] bytes = ip.GetAddressBytes(); return (long) ( 16777216 * (long)bytes[0] + 65536 * (long)bytes[1] + 256 * (long)bytes[2] + (long)bytes[3] ) ; } else return 0; } 

Mi pregunta fue cerrada, no tengo idea de por qué. La respuesta aceptada aquí no es lo mismo que lo que necesito.

Esto me da el valor entero correcto para una IP ..

 public double IPAddressToNumber(string IPaddress) { int i; string [] arrDec; double num = 0; if (IPaddress == "") { return 0; } else { arrDec = IPaddress.Split('.'); for(i = arrDec.Length - 1; i >= 0 ; i = i -1) { num += ((int.Parse(arrDec[i])%256) * Math.Pow(256 ,(3 - i ))); } return num; } } 

El reverso de la función de Davy Landman

 string IntToIp(int d) { int v1 = d & 0xff; int v2 = (d >> 8) & 0xff; int v3 = (d >> 16) & 0xff; int v4 = (d >> 24); return v4 + "." + v3 + "." + v2 + "." + v1; } 

Si estaba interesado en la función, no solo la respuesta aquí es cómo se hace:

 int ipToInt(int first, int second, int third, int fourth) { return Convert.ToInt32((first * Math.Pow(256, 3)) + (second * Math.Pow(256, 2)) + (third * 256) + fourth); } 

de first a fourth son los segmentos de la dirección IPv4.

Con UInt32 en el formato apropiado little-endian, aquí hay dos funciones simples de conversión:

 public uint GetIpAsUInt32(string ipString) { IPAddress address = IPAddress.Parse(ipString); byte[] ipBytes = address.GetAddressBytes(); Array.Reverse(ipBytes); return BitConverter.ToUInt32(ipBytes, 0); } public string GetIpAsString(uint ipVal) { byte[] ipBytes = BitConverter.GetBytes(ipVal); Array.Reverse(ipBytes); return new IPAddress(ipBytes).ToString(); } 
 public bool TryParseIPv4Address(string value, out uint result) { IPAddress ipAddress; if (!IPAddress.TryParse(value, out ipAddress) || (ipAddress.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)) { result = 0; return false; } result = BitConverter.ToUInt32(ipAddress.GetAddressBytes().Reverse().ToArray(), 0); return true; } 
  public static Int32 getLongIPAddress(string ipAddress) { return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0)); } 

El ejemplo anterior sería la forma en que voy. Lo único que tendrías que hacer es convertir a un UInt32 para fines de visualización o con fines de cadena, incluido su uso como una dirección larga en forma de cadena.

Que es lo que se necesita cuando se usa la función IPAddress.Parse (String). Suspiro.

Se ensamblaron varias de las respuestas anteriores en un método de extensión que maneja la Endianness de la máquina y maneja las direcciones IPv4 que se mapearon en IPv6.

 public static class IPAddressExtensions { ///  /// Converts IPv4 and IPv4 mapped to IPv6 addresses to an unsigned integer. ///  /// The address to conver /// An unsigned integer that represents an IPv4 address. public static uint ToUint(this IPAddress address) { if (address.AddressFamily == AddressFamily.InterNetwork || address.IsIPv4MappedToIPv6) { var bytes = address.GetAddressBytes(); if (BitConverter.IsLittleEndian) Array.Reverse(bytes); return BitConverter.ToUInt32(bytes, 0); } throw new ArgumentOutOfRangeException("address", "Address must be IPv4 or IPv4 mapped to IPv6"); } } 

Pruebas unitarias:

 [TestClass] public class IPAddressExtensionsTests { [TestMethod] public void SimpleIp1() { var ip = IPAddress.Parse("0.0.0.15"); uint expected = GetExpected(0, 0, 0, 15); Assert.AreEqual(expected, ip.ToUint()); } [TestMethod] public void SimpleIp2() { var ip = IPAddress.Parse("0.0.1.15"); uint expected = GetExpected(0, 0, 1, 15); Assert.AreEqual(expected, ip.ToUint()); } [TestMethod] public void SimpleIpSix1() { var ip = IPAddress.Parse("0.0.0.15").MapToIPv6(); uint expected = GetExpected(0, 0, 0, 15); Assert.AreEqual(expected, ip.ToUint()); } [TestMethod] public void SimpleIpSix2() { var ip = IPAddress.Parse("0.0.1.15").MapToIPv6(); uint expected = GetExpected(0, 0, 1, 15); Assert.AreEqual(expected, ip.ToUint()); } [TestMethod] public void HighBits() { var ip = IPAddress.Parse("200.12.1.15").MapToIPv6(); uint expected = GetExpected(200, 12, 1, 15); Assert.AreEqual(expected, ip.ToUint()); } uint GetExpected(uint a, uint b, uint c, uint d) { return (a * 256u * 256u * 256u) + (b * 256u * 256u) + (c * 256u) + (d); } } 

he aquí una solución que resolví hoy (¡debería haber buscado primero en Google!):

  private static string IpToDecimal2(string ipAddress) { // need a shift counter int shift = 3; // loop through the octets and compute the decimal version var octets = ipAddress.Split('.').Select(p => long.Parse(p)); return octets.Aggregate(0L, (total, octet) => (total + (octet << (shift-- * 8)))).ToString(); } 

Estoy usando LINQ, lambda y algunas de las extensiones en generics, por lo que, aunque produce el mismo resultado, utiliza algunas de las nuevas características del lenguaje y puede hacerlo en tres líneas de código.

tengo la explicación en mi blog si estás interesado.

vivas, -jc

Creo que esto está mal: “65536” ==> 0.0.255.255 “Debería ser:” 65535 “==> 0.0.255.255” o “65536” ==> 0.1.0.0 ”

@Davy Ladman su solución con shift es corrent pero solo para ip comenzando con un número menor o igual a 99, de hecho el primer octeto debe ser lanzado a largo.

De todos modos, la conversión de vuelta con tipo largo es bastante difícil porque almacena 64 bit (no 32 para Ip) y llena 4 bytes con ceros

 static uint ToInt(string addr) { return BitConverter.ToUInt32(IPAddress.Parse(addr).GetAddressBytes(), 0); } static string ToAddr(uint address) { return new IPAddress(address).ToString(); } 

¡Disfrutar!

Massimo

Suponiendo que tiene una dirección IP en formato de cadena (por ejemplo, 254.254.254.254)

 string[] vals = inVal.Split('.'); uint output = 0; for (byte i = 0; i < vals.Length; i++) output += (uint)(byte.Parse(vals[i]) << 8 * (vals.GetUpperBound(0) - i)); 
 var ipAddress = "10.101.5.56"; var longAddress = long.Parse(string.Join("", ipAddress.Split('.').Select(x => x.PadLeft(3, '0')))); Console.WriteLine(longAddress); 

Salida: 10101005056

 var address = IPAddress.Parse("10.0.11.174").GetAddressBytes(); long m_Address = ((address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0]) & 0x0FFFFFFFF); 

Eche un vistazo a algunos de los ejemplos de análisis loco en .NET’s IPAddress.Parse: ( MSDN )

“65536” ==> 0.0.255.255
“20.2” ==> 20.0.0.2
“20.65535” ==> 20.0.255.255
“128.1.2” ==> 128.1.0.2