質問
サーバーアプリの場合、IPアドレスがブラックリストに含まれているかどうかを確認する必要があります。
IPアドレスを比較する最も効率的な方法は何ですか? IPアドレスを整数に変換し、それらを比較すると効率的ですか?
解決
使用している言語によって異なりますが、IPアドレスは通常、少なくともネットワーク層で32ビットの符号なし整数として保存され、非常に高速に比較できます。そうでなくても、高性能のパケットスイッチングアプリケーションを設計している場合を除き、パフォーマンスのボトルネックになることはほとんどありません。時期尚早な最適化を避ける-テスト容易性とスケーラビリティのためにプログラムを設計し、パフォーマンスの問題がある場合は、プロファイラーを使用してボトルネックの場所を確認できます。
編集:明確にするために、IPv4アドレスは32ビット整数とネットマスク(IPアドレスの比較には不要)として保存されます。より新しく、現在では珍しいIPv6を使用している場合、アドレスは128ビット長になります。
他のヒント
32ビット整数は、128ビットIPv6アドレスの処理を開始するまでの道です。
テキスト文字列として比較するか、intをintに変換してintとして比較する必要があるかということですか?
これは通常、この種の検索のボトルネックではありません。両方のメソッドを実装して、どちらが高速に実行されるかを確認してください。
IPアドレスルックアップの実際の問題は、通常、効率的なクエリを作成することであり、乱数だけでなくIPアドレスを扱っているという事実を利用しています。これを実現するには、 LCトライ、および
私が正しく理解していれば、これは2つのIPアドレスを比較するためのコードです。これが欲しい?さらに次のようなことができます: アドレスバイトを取得したため。static public bool IsEqual(string ToCompare,
string CompareAgainst)
{
return IPAddressToLongBackwards(ToCompare)==IPAddressToLongBackwards(CompareAgainst);
}
static private uint IPAddressToLongBackwards(string IPAddr)
{
System.Net.IPAddress oIP=System.Net.IPAddress.Parse(IPAddr);
byte[] byteIP=oIP.GetAddressBytes();
uint ip=(uint)byteIP[0]<<24;
ip+=(uint)byteIP[1]<<16;
ip+=(uint)byteIP[2]<<8;
ip+=(uint)byteIP[3];
return ip;
}
static public bool IsGreater(string ToCompare,
string CompareAgainst)
{
return IPAddressToLongBackwards(ToCompare)>
IPAddressToLongBackwards(CompareAgainst);
}
はい、私は効率的であることがわかりましたが、それは長くなります、そしてもちろんあなたは整数形式でブラックリストに載ったIPをインデックスしなければなりません。
PeerGuardianなどのツールを使用して、ドライバーレベルでブラックリスト上のIPへの着信TCP / IP接続を禁止します。安全性が高く、コードは不要です(ほぼ間違いなく、安全性が高い、コードが不要)。
これを行ってテストしましたが、unsigned int(32ビット)を使用するのが最も高速です。これを文字列表現と比較していると仮定しています。
テーブルを作成するときに役立つもう1つのことは、過去にLowIPとHighIPの2つの列があったことです。そうすれば、1つのレコードエントリでIPの全範囲をブラックリストに載せることができ、範囲内のIPをチェックすることで優れたパフォーマンスを得ることができます。
以前は、IPアドレスを4 intとして保存するのは本当に良いことだと誰かが考えていたコードを継承していました。
それらをデータベース内の文字列として保持する方がはるかに簡単であり、必要なインデックスは1つだけです。 4列の整数ではなく、SQL Serverが文字列のインデックスを作成できることに驚かれることでしょう。しかし、このIPリストはブラックリスト用ではありませんでした。データベースの往復にはかなりの費用がかかります。
データベースが過剰な場合は、メモリ内の辞書に保存しますが、比較する必要がある数が分からないため、これは推測にすぎません。ほとんどのハッシュコードは32ビット整数であり、IPv4アドレスは32ビットであるため、IPアドレス自体が適切なハッシュコードである可能性があります。
しかし、他の人が指摘しているように、最良の選択肢は、サーバーの負荷を減らして専用のハードウェアを購入することです。たぶん、最近ブラックリストに登録されたIPをメモリに保持し、定期的に新しいIPをルーターに公開します。
ルーター内でソフトウェアを作成しようとしている場合、データ構造の本を探し出し、Bツリーのようなものを作成する必要があります。
基数またはパトリシアトライは、これに最適な構造です。
flow-toolsのCソースをチェックアウトします。 http://www.splintered.net/sw/flow-tools/
私はこの数年前に取り組みました。
既存の効率の問題はありますか?
その場合、必ずコード(または擬似コード)を投稿してください。そうすれば、死体を拾うことができます。
そうでない場合は、ソートされたリストにエントリを保存し、環境の既存の Sort()
と Find()
を使用するなどの簡単な方法を試してみることをお勧めします。
整数の比較は、文字列の比較よりもはるかに高速です。
整数をソートされたリストに保存すると、ソートされていないリストよりも速く見つけることができます。
IPアドレスを文字列として受け取った場合、それを文字列と比較する方が、整数表現に変換するよりも効率的かもしれません
ただし、この操作で数ミリ秒(ナノ秒!)が問題になる場合は、両方のソリューションを確実にプロファイルします;-)