Frage

Unter IPv4 Ich habe die String -Darstellung von IP -Adressen an Parsen analysiert Int32 und sie speichern als INT in dem SQL Server.

Jetzt mit IPv6 Ich versuche herauszufinden, ob es einen Standard oder eine akzeptierte Möglichkeit gibt, die String -Darstellung von zu analysieren IPv6 zu zwei Int64 Verwendung C#?

Auch wie speichern Menschen diese Werte in der SQL Server - als zwei Felder von BIGINT?

War es hilfreich?

Lösung

Da eine IPv4 -Adresse wirklich eine 32 -Bit -Nummer ist, ist eine IPv6 -Adresse wirklich eine 128 -Bit -Nummer. Es gibt unterschiedliche Zeichenfolge Darstellungen der Adressen, aber die tatsächliche Adresse ist die Nummer, nicht die Zeichenfolge.

Sie konvertieren also keine IP -Adresse in eine Nummer, Sie analysieren eine String -Darstellung der Adresse in die tatsächliche Adresse.

Nicht einmal a decimal kann eine 128 -Bit -Zahl halten, so dass drei offensichtliche Alternativen hinterlassen werden:

  • Speichern Sie den numerischen Wert aufgeteilt in zwei bigint Felder
  • Speichern Sie eine String -Darstellung der Adresse in a varchar aufstellen
  • Speichern Sie den numerischen Wert in einem 16 -Byte binary aufstellen

Weder ist so bequem wie das Speichern einer IPv4 -Adresse in einem int, Sie müssen also ihre Grenzen mit dem, was Sie mit den Adressen tun müssen, berücksichtigen.

Andere Tipps

Die einfachste Route besteht darin, den Rahmen für Sie zu tun. Verwenden IPAddress.Parse dann die Adresse analysieren, dann IPAddress.GetAddressBytes um die "Nummer" als Byte [] zu erhalten.

Schließlich teilen MemoryStream über dem Byte -Array und dann über a lesen BinaryReader.

Dadurch wird vermieden, dass alle verfügbaren Abkürzungen für IPv6 -Adressen verstehen müssen.

Wenn Sie SQL Server 2005 verwenden, können Sie die verwenden uniqueidentifier Typ. Dieser Typ speichert 16 Bytes, was perfekt für eine IPv6 -IP -Adresse ist. Sie können zwischeneinander konvertieren IPAddress und Guid durch Verwendung der Konstrukteure und ToByteArray.

Ich verwende die folgende Methode zum Konvertieren einer IP -Adresse in zwei 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;
}

Stellen Sie sicher, dass Sie Ihre werfen UInt64s zu Int64s, bevor Sie sie in die Datenbank einfügen, oder Sie erhalten eine ArgumentException. Wenn Sie Ihre Werte wieder herausholen, können Sie sie zurückwerfen UInt64 um den nicht signierten Wert zu erhalten.

Ich muss nicht umgekehrt sein (dh konvertieren a UInt64[2] zu einer IP -Zeichenfolge) also habe ich nie eine Methode dafür erstellt.

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']);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top