Domanda

Sotto IPv4 Ho analizzato la rappresentazione della stringa degli indirizzi IP Int32 e conservarli come INT nel SQL Server.

Ora, con IPv6 Sto cercando di scoprire se esiste un modo standard o accettato per analizzare la rappresentazione delle stringhe di IPv6 a due Int64 usando C#?

Anche come le persone immagazzinano quei valori in SQL Server - come due campi di BIGINT?

È stato utile?

Soluzione

Proprio come un indirizzo IPv4 è davvero un numero di 32 bit, un indirizzo IPv6 è davvero un numero di 128 bit. Esistono diverse rappresentazioni di stringhe degli indirizzi, ma l'indirizzo effettivo è il numero, non la stringa.

Quindi, non si convertisce un indirizzo IP in un numero, analizzi una rappresentazione della stringa dell'indirizzo nell'indirizzo effettivo.

Neanche a decimal può contenere un numero di 128 bit, in modo che lascia tre ovvie alternative:

  • memorizzare il valore numerico diviso in due bigint campi
  • memorizzare una rappresentazione di stringa dell'indirizzo in a varchar campo
  • Conservare il valore numerico in un byte a 16 anni binary campo

Né è conveniente come la memorizzazione di un indirizzo IPv4 in un int, quindi devi considerare i loro limiti contro ciò che devi fare con gli indirizzi.

Altri suggerimenti

Il percorso più semplice è ottenere il framework per farlo per te. Uso IPAddress.Parse per analizzare l'indirizzo, quindi IPAddress.GetAddressBytes Per ottenere il "numero" come byte [].

Infine, dividi l'array nel primo e nel secondo 8 byte per la conversione in due int64, ad es. MemoryStream sopra l'array di byte e poi leggere tramite un BinaryReader.

Ciò evita di dover comprendere tutte le rappresentazioni a scorrimento disponibili per gli indirizzi IPv6.

Se si utilizza SQL Server 2005, è possibile utilizzare il uniqueidentifier genere. Questo tipo memorizza 16 byte, che è perfetto per un indirizzo IP IPv6. Puoi convertire tra IPAddress e Guid usando i costruttori e ToByteArray.

Uso il seguente metodo per convertire un indirizzo IP in due 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;
}

Assicurati di lanciare il tuo UInt64s a Int64s prima di metterli nel database o otterrai un ArgumentException. Quando ricevi i tuoi valori, puoi restituirli UInt64 Per ottenere il valore non firmato.

Non ho bisogno di fare il contrario (cioè convertire a UInt64[2] a una stringa IP) quindi non ho mai creato un metodo per questo.

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']);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top