2016-10-14 8 views
-1

私はこれらのテーブルの一つが、この構造を有し、(特に都市/国レベルまで)Maxmindのジオロケーション・テーブルを使用しています:スタンドアロンIPとCIDRをどのように一致させることができますか?

enter image description here

私は別のテーブルでの私のサービスの利用者のIPアドレスを格納します。私はlatitudelongitudeの列を作成し、これらのIPの該当する緯度と経度を(IPの対応する行にある)ユーザー表内に格納したいとします。

見られるように、MaxMindテーブル内のIPアドレスは、それが直接にIPがCIDRによって与えられたIP範囲内に収まるかどうかをチェックことはできません。つまり、CIDR形式で保存されています。

MySQLの文だけを使用して、通常のIPをCIDR形式に一致させることは可能ですか?

私はこれを試してみましたが、しかし、次を発見した:私はサブネットを取得することができます

    • それが可能ですが、私は(私が持っていない)サブネットマスクを必要とします

    MaxMindテーブル内のCIDR表記にusersテーブルにIPアドレスを照合すると、しばらく時間がかかるだろうと

  • 、私はusinよ...しかし、それはCIDRを必要とし、生のIPからマスクGAバッチを処理するための標準的なC#CLIプログラム、と私は私がこれを行うことができますことを認める:

    1. ゴー各行しかしデータリーダーに全体 MaxMindテーブルを取得しにCIDRを変換します同時に、IPの範囲
    2. は、usersテーブルにデータリーダーを開いて、IP範囲に与えられたIPと一致
    3. UPDATE以前
    4. からCIDRに一致する緯度と経度と usersに対応するレコード

    ご覧のとおり、私の方法は非常に非効率的で、必要以上に多くの時間がかかることがあります。


    MySQLの文を使用するだけで、通常のIPとCIDRを一致させることはできますか?そうでない場合は、サブネットマスクなしで計算してIPに一致させることはできますか?次のようにusersテーブル内の関連する

    列は以下のとおりです。

    enter image description here

    +0

    「単純にMySQL文を使用して通常のIPとCIDRを一致させることはできますか?」いいえ。「サブネットマスクなしでIP範囲を計算してからIPに一致させることはできますか?」いいえ、どのようにしてサブネットマスクのない範囲を知ることができますか? – itsme86

    +0

    1つの方法は、列を追加することです。結局のところ、CIDRはアドレスのネットワーク部分のビットマスクに過ぎません。したがって、各範囲では、ネットワーク部分だけを持つ列(整数)があります。次に、探しているIPを取って最終的にネットワーク部分を短くしたり短くしたりすることができます。それは<23クエリです。ブルートフォースと醜い。あなただけのMySQLでそれを行うことはできますか?私は驚くだろう。 – Duston

    +0

    @ itsme86私は、有料のジオロケーションサービスに頼らずに、私が自由に使えるものを使ってIPの緯度と経度を 'users'テーブルに保存する方法を見つけようとしています。 – cybermonkey

    答えて

    0

    それが助け場合、私はIPアドレスが範囲内に収まるかどうかをチェックするためにいくつかの時間前にこのクラスを書きました。ネットワークとマスクをCIDR文字列で分割し、それらを解析してコンストラクタに渡すだけです。次に、ContainsIP()を使用して、そのIPアドレスがそのネットワーク内にあるかどうかを確認できます。おそらく、あなたのために分割/解析を処理するためにCIDR文字列を受け付ける別のコンストラクタを使用する可能性があります。

    public class IPNetwork 
    { 
        private readonly IPAddress _networkMask; 
        private readonly int _networkMaskLength; 
        private readonly uint _networkMaskValue; 
    
        public IPNetwork(IPAddress networkMask, int networkMaskLength) 
        { 
         if (networkMask.AddressFamily != AddressFamily.InterNetwork) 
          throw new InvalidOperationException("Only IPv4 networks are supported."); 
    
         _networkMask = networkMask; 
         _networkMaskLength = networkMaskLength; 
         _networkMaskValue = GetMaskedAddress(networkMask); 
        } 
    
        public bool ContainsIP(IPAddress ipAddress) 
        { 
         return GetMaskedAddress(ipAddress) == _networkMaskValue; 
        } 
    
        private uint GetMaskedAddress(IPAddress ipAddress) 
        { 
         byte[] bytes = ipAddress.GetAddressBytes(); 
         int addressLength = bytes.Length * 8; 
         uint addressValue = BytesToValue(bytes); 
    
         uint maskedAddress = 0; 
         for (int i = addressLength - _networkMaskLength; i < addressLength; ++i) 
          maskedAddress |= addressValue & (1U << i); 
    
         return maskedAddress; 
        } 
    
        private uint BytesToValue(byte[] bytes) 
        { 
         uint value = 0; 
    
         for (int i = 0; i < bytes.Length; ++i) 
          value |= (uint)(bytes[bytes.Length - i - 1] << (i * 8)); 
    
         return value; 
        } 
    } 
    
    関連する問題