Pregunta

Por debajo IPv4 He estado analizando la representación de cadenas de direcciones IP a Int32 y almacenarlos como INT en el SQL Server.

Ahora con IPv6 Estoy tratando de averiguar si hay una forma estándar o aceptada de analizar la representación de la cadena de IPv6 para dos Int64 usando C#?

También cómo las personas almacenan esos valores en el SQL Server - Como dos campos de BIGINT?

¿Fue útil?

Solución

Así como una dirección IPv4 es realmente un número de 32 bits, una dirección IPv6 es realmente un número de 128 bits. Existen diferentes representaciones de cadena de las direcciones, pero la dirección real es el número, no la cadena.

Por lo tanto, no convierte una dirección IP en un número, analiza una representación de cadena de la dirección en la dirección real.

Ni siquiera un decimal Puede contener un número de 128 bits, por lo que deja tres alternativas obvias:

  • Almacene el valor numérico dividido en dos bigint campos
  • almacenar una representación de cadena de la dirección en un varchar campo
  • Almacene el valor numérico en un byte de 16 binary campo

Tampoco es tan conveniente como almacenar una dirección IPv4 en un int, por lo que debe considerar sus limitaciones contra lo que necesita hacer con las direcciones.

Otros consejos

La ruta más simple es obtener el marco para hacer esto por usted. Usar IPAddress.Parse para analizar la dirección, entonces IPAddress.GetAddressBytes Para obtener el "número" como byte [].

Finalmente, divida la matriz en el primer y segundo 8 bytes para la conversión a dos int64s, por ejemplo, creando un MemoryStream sobre la matriz de bytes y luego leyendo a través de un BinaryReader.

Esto evita la necesidad de comprender todas las representaciones cortas disponibles para las direcciones IPv6.

Si está utilizando SQL Server 2005, puede usar el uniqueidentifier escribe. Este tipo almacena 16 bytes, que es perfecto para una dirección IP IPv6. Puedes convertir entre IPAddress y Guid mediante el uso de los constructores y ToByteArray.

I use the following method for converting an IP address to two UInt64s (C# 3.0).

/// <summary>
/// Converts an IP address to its UInt64[2] equivalent.
/// For an IPv4 address, the first element will be 0,
/// and the second will be a UInt32 representation of the four bytes.
/// For an IPv6 address, the first element will be a UInt64
/// representation of the first eight bytes, and the second will be the
/// last eight bytes.
/// </summary>
/// <param name="ipAddress">The IP address to convert.</param>
/// <returns></returns>
private static ulong[] ConvertIPAddressToUInt64Array(string ipAddress)
{
    byte[] addrBytes = System.Net.IPAddress.Parse(ipAddress).GetAddressBytes();
    if (System.BitConverter.IsLittleEndian)
    {
        //little-endian machines store multi-byte integers with the
        //least significant byte first. this is a problem, as integer
        //values are sent over the network in big-endian mode. reversing
        //the order of the bytes is a quick way to get the BitConverter
        //methods to convert the byte arrays in big-endian mode.
        System.Collections.Generic.List<byte> byteList = new System.Collections.Generic.List<byte>(addrBytes);
        byteList.Reverse();
        addrBytes = byteList.ToArray();
    }
    ulong[] addrWords = new ulong[2];
    if (addrBytes.Length > 8)
    {
        addrWords[0] = System.BitConverter.ToUInt64(addrBytes, 8);
        addrWords[1] = System.BitConverter.ToUInt64(addrBytes, 0);
    }
    else
    {
        addrWords[0] = 0;
        addrWords[1] = System.BitConverter.ToUInt32(addrBytes, 0);
    }
    return addrWords;
}

Make sure you cast your UInt64s to Int64s before you put them into the database, or you'll get an ArgumentException. When you get your values back out, you can cast them back to UInt64 to get the unsigned value.

I don't have a need to do the reverse (i.e. convert a UInt64[2] to an IP string) so I never built a method for it.

function encode_ip ($ip)
{
    return bin2hex(inet_pton($ip));
}

function decode_ip($ip)
{
    function hex2bin($temp) {
       $data="";
       for ($i=0; $i < strlen($temp); $i+=2) $data.=chr(hexdec(substr($temp,$i,2)));
       return $data;
    }
    return inet_ntop(hex2bin($ip));
}

-- max len row db
echo strlen(inet_pton('2001:db8:85a3::8a2e:370:7334'));

-- db row info
ip varchar(16)

-- sql binary save and read
save base
$bin_ip='0x'.bin2hex(inet_pton($data['ip_address']));

-- db read
select ip_address from users;

-- encode binary from db
echo inet_ntop($row['ip_address']);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top