Question

En dessous de IPv4 J'ai analysé la représentation de chaîne des adresses IP à Int32 et les stocker comme INT dans le SQL Server.

Maintenant avec IPv6 J'essaie de savoir s'il y a un moyen standard ou accepté d'analyser la représentation des cordes de IPv6 à deux Int64 utilisant C#?

Aussi comment les gens stockent ces valeurs dans le SQL Server - comme deux champs de BIGINT?

Était-ce utile?

La solution

Tout comme une adresse IPv4 est vraiment un numéro 32 bits, une adresse IPv6 est vraiment un numéro 128 bits. Il existe différentes représentations de chaînes des adresses, mais l'adresse réelle est le nombre, pas la chaîne.

Ainsi, vous ne convertissez pas une adresse IP en nombre, vous analysez une représentation de chaîne de l'adresse en l'adresse réelle.

Pas même un decimal Peut contenir un nombre de 128 bits, ce qui laisse trois alternatives évidentes:

  • stocker la valeur numérique divisée en deux bigint des champs
  • Stockez une représentation de chaîne de l'adresse dans un varchar champ
  • Stockez la valeur numérique dans un octet de 16 ans binary champ

Ni l'un ni l'autre n'est aussi pratique que le stockage d'une adresse IPv4 dans un int, vous devez donc considérer leurs limites à ce que vous devez faire avec les adresses.

Autres conseils

L'itinéraire le plus simple est d'obtenir le cadre pour le faire pour vous. Utilisation IPAddress.Parse Pour analyser l'adresse, alors IPAddress.GetAddressBytes Pour obtenir le "numéro" comme octet [].

Enfin, divisez le tableau en première et deuxième 8 octets pour la conversion en deux INT64, par exemple en créant un MemoryStream sur le tableau d'octets puis lire via un BinaryReader.

Cela évite d'avoir besoin de comprendre toutes les représentations de raccourci disponibles pour les adresses IPv6.

Si vous utilisez SQL Server 2005, vous pouvez utiliser le uniqueidentifier taper. Ce type stocke 16 octets, ce qui est parfait pour une adresse IP IPv6. Vous pouvez convertir entre IPAddress et Guid en utilisant les constructeurs et ToByteArray.

J'utilise la méthode suivante pour convertir une adresse IP en deux 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;
}

Assurez-vous de lancer votre UInt64s à Int64s avant de les mettre dans la base de données, ou vous obtiendrez un ArgumentException. Lorsque vous récupérez vos valeurs, vous pouvez les rejeter vers UInt64 pour obtenir la valeur non signée.

Je n'ai pas besoin de faire l'inverse (c'est-à-dire convertir un UInt64[2] à une chaîne IP) donc je n'ai jamais construit de méthode pour cela.

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']);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top