2009-04-21 99 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']); 
相關問題