21

IPv4我一直在解析 IP 地址的字符串表示形式Int32并将它们存储INTSQL Server.

现在,IPv6我试图找出是否有标准或可接受的方法来解析字符串表示IPv6为两个Int64使用C#

另外,人们如何将这些值存储在SQL Server- as 的两个字段中BIGINT

4

5 回答 5

20

正如 IPv4 地址实际上是一个 32 位数字一样,IPv6 地址实际上是一个 128 位数字。地址有不同的字符串表示,但实际地址是数字,而不是字符串。

因此,您无需将 IP 地址转换为数字,而是将地址的字符串表示形式解析为实际地址。

甚至 adecimal都不能容纳 128 位数字,因此留下了三个明显的替代方案:

  • 存储分成两个bigint字段的数值
  • 将地址的字符串表示形式存储在varchar字段中
  • 将数值存储在 16 字节binary字段中

两者都不像将 IPv4 地址存储在int.

于 2009-04-21T21:44:38.467 回答
12

最简单的方法是让框架为您执行此操作。用于IPAddress.Parse解析地址,然后IPAddress.GetAddressBytes将“数字”作为字节[]获取。

最后,将数组分成第一个和第二个 8 字节,以转换为两个 Int64,例如通过MemoryStream在字节数组上创建 a 然后通过 a 读取BinaryReader

这避免了需要了解 IPv6 地址的所有可用快捷方式表示。

于 2009-04-22T09:48:00.880 回答
4

如果您使用的是 SQL Server 2005,则可以使用该uniqueidentifier类型。此类型存储 16 个字节,非常适合 IPv6 ip 地址。您可以使用构造函数在IPAddress和之间进行转换 和。GuidToByteArray

于 2010-02-23T23:56:42.220 回答
3

我使用以下方法将 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;
}

确保在将它们放入数据库之前将UInt64s 转换为s,否则您将得到一个. 当您恢复您的值时,您可以将它们转换回以获取无符号值。Int64ArgumentExceptionUInt64

我不需要做相反的事情(即将 a 转换UInt64[2]为 IP 字符串),所以我从来没有为它构建方法。

于 2009-10-29T21:19:39.777 回答
0
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']);
于 2011-12-04T14:59:22.133 回答