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





int de (18)


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();
}

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 #.




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
{
    /// <summary>
    /// Converts IPv4 and IPv4 mapped to IPv6 addresses to an unsigned integer.
    /// </summary>
    /// <param name="address">The address to conver</param>
    /// <returns>An unsigned integer that represents an IPv4 address.</returns>
    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 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;
}



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()));



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();
}



    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.




@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 sumarlos 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);
}



@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




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 .




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;
}



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




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 genéricos, 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




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;
    }
}



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 programa 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));
    }
}



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.




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;
}



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



Al comparar los artículos de MSDN "Novedades en el lenguaje y compilador de C # 2.0" y " Novedades en Visual C # 2005 ", es posible deducir que "C # major_version.minor_version" está acuñado de acuerdo con la numeración de la versión del compilador.

Hay un C # 1.2 correspondiente a .NET 1.1 y VS 2003 y también denominado Visual C # .NET 2003 .

Pero más adelante, Microsoft se detuvo para incrementar los números de la versión secundaria (después del punto) o para que no fueran cero, 0 . Aunque se debe tener en cuenta que C # correspondiente a .NET 3.5 se nombra en msdn.microsoft.com como "Visual C # 2008 Service Pack 1" .

Hay dos nombres paralelos: por .NET principal / numeración de versión del compilador y por numeración de Visual Studio.

C # 2.0 es un sinónimo de Visual C # 2005

C # 3.0 corresponde (o, más correctamente, puede apuntar) a:





c# integer ip ipv4