Форматирование IPv6 как int в C # и сохранение его в SQL Server - PullRequest
21 голосов
/ 22 апреля 2009

Под IPv4 Я проанализировал строковое представление IP-адресов на Int32 и сохранил их как INT в SQL Server.

Теперь, с помощью IPv6 Я пытаюсь выяснить, существует ли стандартный или общепринятый способ разбора строкового представления IPv6 на два Int64 с использованием C#?

Кроме того, как люди хранят эти значения в SQL Server - как два поля BIGINT?

Ответы [ 5 ]

19 голосов
/ 22 апреля 2009

Так же, как адрес IPv4 на самом деле является 32-битным числом, адрес IPv6 на самом деле является 128-битным числом. Существуют разные строковые представления адресов, но фактический адрес - это число, а не строка.

Таким образом, вы не конвертируете IP-адрес в число, вы анализируете строковое представление адреса в фактический адрес.

Даже decimal не может содержать 128-битное число, так что остается три очевидных альтернативы:

  • сохранить числовое значение, разделенное на два поля bigint
  • сохранить строковое представление адреса в varchar поле
  • сохранить числовое значение в 16-байтовом binary поле

Это не так удобно, как хранить IPv4-адрес в int, поэтому вы должны учитывать их ограничения относительно того, что вам нужно делать с адресами.

12 голосов
/ 22 апреля 2009

Самый простой способ - это заставить систему сделать это для вас. Используйте IPAddress.Parse для анализа адреса, затем IPAddress.GetAddressBytes, чтобы получить «число» в виде байта [].

Наконец, разделите массив на первый и второй 8 байтов для преобразования в два Int64, например, путем создания MemoryStream над байтовым массивом и последующего чтения через BinaryReader.

Это исключает необходимость понимания всех доступных сокращенных представлений для адресов IPv6.

4 голосов
/ 24 февраля 2010

Если вы используете SQL Server 2005, вы можете использовать тип uniqueidentifier. Этот тип хранит 16 байтов, что идеально подходит для IP-адреса IPv6. Вы можете конвертировать между IPAddress и Guid с помощью конструкторов и ToByteArray.

3 голосов
/ 30 октября 2009

Я использую следующий метод для преобразования IP-адреса в два UInt64 s (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;
}

Убедитесь, что вы нацелили свои UInt64 с Int64 с, прежде чем поместить их в базу данных, иначе вы получите ArgumentException Когда вы вернете свои значения, вы можете привести их обратно к UInt64, чтобы получить значение без знака.

У меня нет необходимости делать обратное (т.е. преобразовывать UInt64[2] в строку IP), поэтому я никогда не создавал метод для этого.

0 голосов
/ 04 декабря 2011
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']);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...