Форматирование IPv6 как int в C# и хранение в SQL Server

StackOverflow https://stackoverflow.com/questions/774536

  •  13-09-2019
  •  | 
  •  

Вопрос

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

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

Также как люди хранят эти ценности в SQL Server - как два поля BIGINT?

Это было полезно?

Решение

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

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

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

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

Ни один из них не так удобен, как хранение адреса IPv4 в int, Таким образом, вы должны рассмотреть их ограничения в отношении того, что вам нужно делать с адресами.

Другие советы

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

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

Это избегает необходимости понимать все доступные короткие представления для адресов IPv6.

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

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

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

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

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']);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top