2009-04-21 5 views
19

IPv4の下では、IPアドレスの文字列表現をInt32に解析し、SQL ServerINTとして保存しています。C#でintとしてIPv6をフォーマットし、それをSQL Serverに格納

IPv6IPv6の文字列表現を2つの文字に変換する標準的な方法があるかどうかを確認しようとしていますC#を使用していますか?

これらの値をSQL Serverに保存する人々は、どのように2つのフィールドをBIGINTとしていますか?

答えて

17

IPv4アドレスが実際には32ビット数であるのと同様に、IPv6アドレスは実際には128ビット数です。アドレスの文字列表現はさまざまですが、実際のアドレスは文字列ではなく数値です。

したがって、IPアドレスを数値に変換しない場合は、アドレスの文字列表現を解析して実際のアドレスに変換します。 varcharで2つのbigintフィールドへ

  • ストアアドレスの文字列表現を

    • ストア数値分割:それは3つの明白な選択肢を残して

      でもdecimalは、128ビットの数を保持できるわけではありませんフィールド
    • 店16バイトbinaryフィールドに数値

    N intにIPv4アドレスを格納するのと同じくらい便利なので、アドレスの処理に制限があることを考慮する必要があります。

  • +2

    @Bill:あなたは間違っています。 IPv4アドレスのバイトを符号なしの値に格納する必要があるということは何もありません。 Int32にはUInt32と同じ32ビットがあるため、4バイトの格納には問題ありません。 – Guffa

    +0

    良いこと@RBarryYoungはこのスレッドを見つけませんでした;-) http://stackoverflow.com/a/1385701/215068 IPv4は4バイトのバイナリであり、実際には32ビットの番号ではありません。 4桁の3桁のオクテットは便利な表記です – EBarr

    +0

    @EBarr:いいえ、バージョン4のIP番号は* 32ビットの数字ですが、4バイトの数字ではありません。 IPパケットの説明を見ると、アドレスは32ビットの単一の単位であることがわかります。アドレスは4つの8ビット値に分割されていません。 – Guffa

    10

    最も簡単な方法は、これを行うためのフレームワークを取得することです。 IPAddress.Parseを使用してアドレスを解析し、次にIPAddress.GetAddressBytesを使用して、数字[]をバイト[]として取得します。

    最後に、2つのInt64に変換するために、配列を1番目と2番目の8バイトに分割します。バイト配列上にMemoryStreamを作成し、次にBinaryReaderを介して読み取ります。

    これにより、IPv6アドレスの使用可能なショートカット表現をすべて理解する必要がなくなります。

    +0

    なぜ2のint64の代わりにバイナリ(128)フィールド? – Henry

    +0

    @Henry:それはQが指定したものです。 – Richard

    3

    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文字列に変換する必要はありません)。

    +0

    255.255.255.255またはFFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFFを保存するケースはほとんどありません。 – Gavin

    +1

    -1:Int32は、IPv4アドレスを格納するのにうまく機能します。あなたは盲目的に整数の最大値を見つめていますが、それは無関係です。 32ビットは32ビットであり、明らかにIPv4アドレスの4バイトを表現するのに十分である。 – Guffa

    +0

    私の悪い。 UInt32.MaxValueをInt32にキャストしようとすると、「角を曲がる」のではなく、CLRがオーバーフローエラーをスローすると思いました。私はそれを反映するために私の答えを編集しました。 –

    4

    SQL Server 2005を使用している場合は、uniqueidentifierタイプを使用できます。このタイプは16バイトを格納します。これはIPv6のIPアドレスに最適です。コンストラクタとToByteArrayを使用してIPAddressGuidの間で変換できます。

    +4

    'uniqueidentifier'の問題は、範囲検索を行うことができないことです。私。 1つの特定のIPを含むIP範囲を検索することはできません。 ** 3.000.000 **の行のデータでこれを試しました。そして結果として3行の結果になるのではなく、**〜73.000 **行を得ました – NoLifeKing

    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']); 
    
    +3

    これはPHPです、OPはC# – nokturnal

    関連する問題