C#의 int로 IPv6 포맷 및 SQL Server에 저장
-
13-09-2019 - |
문제
아래에 IPv4
IP 주소의 문자열 표현을 구문 분석하고 있습니다. Int32
그리고 그들을 보관합니다 INT
에서 SQL Server
.
이제 IPv6
나는 문자열 표현을 구문 분석하는 표준이거나 받아 들여진 방법이 있는지 알아 내려고 노력하고 있습니다. IPv6
두 개 Int64
사용 C#
?
또한 사람들이 그 가치를 어떻게 저장하고 있습니까? SQL Server
- 두 분야로 BIGINT
?
해결책
IPv4 주소가 실제로 32 비트 번호 인 것처럼 IPv6 주소는 실제로 128 비트 숫자입니다. 주소에는 다른 문자열 표현이 있지만 실제 주소는 문자열이 아닌 숫자입니다.
따라서 IP 주소를 숫자로 변환하지 않으며 주소의 문자열 표현을 실제 주소로 구문 분석합니다.
조차도 decimal
128 비트 번호를 보유 할 수 있으므로 세 가지 명백한 대안을 남깁니다.
- 숫자 값 분할을 2로 저장하십시오
bigint
필드 - 주소의 문자열 표현을 a
varchar
필드 - 숫자 값을 16 바이트에 저장하십시오
binary
필드
IPv4 주소를 int
, 당신은 주소로해야 할 일에 대한 그들의 한계를 고려해야합니다.
다른 팁
가장 간단한 경로는 프레임 워크가 당신을 위해이를 수행하는 것입니다. 사용 IPAddress.Parse
그러면 주소를 구문 분석합니다 IPAddress.GetAddressBytes
"숫자"를 바이트 []로 가져옵니다.
마지막으로, 배열을 첫 번째 및 두 번째 8 바이트로 나누어서 두 개의 int64로 변환합니다. MemoryStream
바이트 어레이를 통해 a BinaryReader
.
이는 IPv6 주소에 사용 가능한 모든 단축 표현을 이해할 필요가 없습니다.
SQL Server 2005를 사용하는 경우 uniqueidentifier
유형. 이 유형은 16 바이트를 저장하며 IPv6 IP 주소에 적합합니다. 당신은 사이를 변환 할 수 있습니다 IPAddress
그리고 Guid
생성자를 사용하여 ToByteArray
.
IP 주소를 2로 변환하기 위해 다음 방법을 사용합니다. 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
s to Int64
s 데이터베이스에 넣기 전에 s가 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']);