2009-04-21 23 views
19

IPv4下,我一直在解析IP地址的字符串表示为Int32并将它们作为INT存储在SQL Server中。在C#中将IPv6格式化为int,并将其存储在SQL Server中

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

此外,人们如何将这些值存储在SQL Server中 - 作为BIGINT的两个字段?

回答

17

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

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

甚至没有一个decimal可以容纳128位的数字,使叶片三个明显的替代品:

  • 店的数值分成两个bigint领域
  • 店地址的字符串表示的varchar字段
  • 存储在一个16字节的数值binary字段

ñ要么就像在int中存储IPv4地址一样方便,所以您必须考虑它们与您需要对地址做什么的限制。

+2

@Bill:你错了。没有什么说您必须将IPv4地址的字节存储为无符号值。 Int32有32位,就像UInt32一样,所以它可以很好地存储4个字节。 – Guffa 2009-10-29 22:20:28

+0

好东西@RBarryYoung没有找到这个线程;-) http://stackoverflow.com/a/1385701/215068 IPv4是4字节的二进制文件,而不是“真正的32位数字”。四个三位八位组只是一个方便的符号 – EBarr 2012-03-30 19:46:50

+0

@EBarr:不,版本4 *中的IP地址是* 32位数字,它不是4字节数字。查看IP数据包的描述,并且您看到地址是32位的单个单元,它们没有分成4个8位值。 – Guffa 2012-03-30 20:04:09

10

最简单的路线是让框架为你做这件事。使用IPAddress.Parse解析地址,然后使用IPAddress.GetAddressBytes以“byte”[]的形式获取“number”。

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

这样可以避免需要了解IPv6地址的所有可用捷径表示。

3

我使用以下方法将IP地址转换为两个UInt64(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 s到Int64是你把它们放到数据库之前,或者你会得到一个ArgumentException。当你将值返回时,你可以将它们转换回UInt64以获得无符号值。

我没有必要做相反的事情(即将UInt64[2]转换为IP字符串),所以我从来没有为它建立过一个方法。

4

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

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']); 
相关问题