IPv4
の下では、IPアドレスの文字列表現をInt32
に解析し、SQL Server
にINT
として保存しています。C#でintとしてIPv6をフォーマットし、それをSQL Serverに格納
IPv6
IPv6
の文字列表現を2つの文字に変換する標準的な方法があるかどうかを確認しようとしていますC#
を使用していますか?
これらの値をSQL Server
に保存する人々は、どのように2つのフィールドをBIGINT
としていますか?
IPv4
の下では、IPアドレスの文字列表現をInt32
に解析し、SQL Server
にINT
として保存しています。C#でintとしてIPv6をフォーマットし、それをSQL Serverに格納
IPv6
IPv6
の文字列表現を2つの文字に変換する標準的な方法があるかどうかを確認しようとしていますC#
を使用していますか?
これらの値をSQL Server
に保存する人々は、どのように2つのフィールドをBIGINT
としていますか?
IPv4アドレスが実際には32ビット数であるのと同様に、IPv6アドレスは実際には128ビット数です。アドレスの文字列表現はさまざまですが、実際のアドレスは文字列ではなく数値です。
したがって、IPアドレスを数値に変換しない場合は、アドレスの文字列表現を解析して実際のアドレスに変換します。 varchar
で2つのbigint
フィールドへ
decimal
は、128ビットの数を保持できるわけではありませんフィールドbinary
フィールドに数値N int
にIPv4アドレスを格納するのと同じくらい便利なので、アドレスの処理に制限があることを考慮する必要があります。
最も簡単な方法は、これを行うためのフレームワークを取得することです。 IPAddress.Parse
を使用してアドレスを解析し、次にIPAddress.GetAddressBytes
を使用して、数字[]をバイト[]として取得します。
最後に、2つのInt64に変換するために、配列を1番目と2番目の8バイトに分割します。バイト配列上にMemoryStream
を作成し、次にBinaryReader
を介して読み取ります。
これにより、IPv6アドレスの使用可能なショートカット表現をすべて理解する必要がなくなります。
IPアドレスを2つの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;
}
データベースにそれらを置く前に、あなたはInt64
秒にごUInt64
秒を投げていることを確認し、またはあなたがArgumentException
を取得します。値を取り戻すときは、UInt64
に戻して符号なしの値を得ることができます。
逆のことをする必要はありません(つまり、UInt64[2]
をIP文字列に変換する必要はありません)。
255.255.255.255またはFFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFFを保存するケースはほとんどありません。 – Gavin
-1:Int32は、IPv4アドレスを格納するのにうまく機能します。あなたは盲目的に整数の最大値を見つめていますが、それは無関係です。 32ビットは32ビットであり、明らかにIPv4アドレスの4バイトを表現するのに十分である。 – Guffa
私の悪い。 UInt32.MaxValueをInt32にキャストしようとすると、「角を曲がる」のではなく、CLRがオーバーフローエラーをスローすると思いました。私はそれを反映するために私の答えを編集しました。 –
SQL Server 2005を使用している場合は、uniqueidentifier
タイプを使用できます。このタイプは16バイトを格納します。これはIPv6のIPアドレスに最適です。コンストラクタとToByteArray
を使用してIPAddress
とGuid
の間で変換できます。
'uniqueidentifier'の問題は、範囲検索を行うことができないことです。私。 1つの特定のIPを含むIP範囲を検索することはできません。 ** 3.000.000 **の行のデータでこれを試しました。そして結果として3行の結果になるのではなく、**〜73.000 **行を得ました – NoLifeKing
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']);
これはPHPです、OPはC# – nokturnal
@Bill:あなたは間違っています。 IPv4アドレスのバイトを符号なしの値に格納する必要があるということは何もありません。 Int32にはUInt32と同じ32ビットがあるため、4バイトの格納には問題ありません。 – Guffa
良いこと@RBarryYoungはこのスレッドを見つけませんでした;-) http://stackoverflow.com/a/1385701/215068 IPv4は4バイトのバイナリであり、実際には32ビットの番号ではありません。 4桁の3桁のオクテットは便利な表記です – EBarr
@EBarr:いいえ、バージョン4のIP番号は* 32ビットの数字ですが、4バイトの数字ではありません。 IPパケットの説明を見ると、アドレスは32ビットの単一の単位であることがわかります。アドレスは4つの8ビット値に分割されていません。 – Guffa