問題の説明は非常に簡単です。ユーザーのIPアドレスによってプロバイダーを決定する必要があります。 その後、このデータを分析システムで使用する必要があります。また、GoogleやRipeなどのデータと比較することもできなければなりません。
この記事で提供されるコードは完全ではないことをすぐに言わなければなりません。 使用されるプログラミング言語はPHPです(もちろん、このようなタスクにはCまたはPerlを使用することをお勧めします)。 データベース-MySQL(ここでは、高速で多数の選択を処理できるデータベースを選択することをお勧めします。たとえば、Tarantool)。 しかし、日常生活では、これらのテクノロジー/言語で十分です。
データベースを検索し、そこからデータを抽出します
それでは始めましょう。 プロバイダーのデータはどこで入手できますか?
RIPEサービスはすぐに選択されました。 欠点は、データベース全体が
テキストファイルに保存されること
です 。 しばらくの間、「グーグルで」MySQL用のコンバーターが見つかりませんでした。 まあ、それはタスクを少し複雑にしました。 しかし、それは問題ではありません。有名なビデオクリップとそのフレーズを思い出してください:「あなたはエキスパートです」。データベースファイルの説明を探し、MySQLでテキスト形式からデータパーサーを書くことにしました。
しかし、少し待ち伏せがありました。 フィールドの
説明はありますが、テーブル間の関係が見つかりませんでした(もちろん、見栄えが悪いかもしれません)。 しかし、これはすでにかなり具体的な問題になっています。
さらに、私は間違った方向に考え始め、何とかその場でファイルのフィールドを一致させようとしました。 つまり、1つのファイルを解析するスクリプトを実行しました(これは非常に「松葉杖」のように覚えています。休日、酔ってしまい、何も覚えていません。翌日、友人はポーチで裸で走り、わいせつな叫び声を上げました。あなたはひどく恥ずかしいです)。
その結果、数時間後(はい、数時間後)、何もしていないことに気付き、すべてのデータをMySQLに格納することにしました。 幸いなことに、データを調査する過程で、比較に必要なフィールドを理解することができました。
データベースにデータをインポートする
フィールドがわかっているため、次のテーブルを作成しました。
CREATE TABLE `test_inetnum` ( `sip` bigint(20) unsigned NOT NULL, `eip` bigint(20) unsigned NOT NULL, `org` varchar(255) NOT NULL, PRIMARY KEY (`sip`,`eip`), KEY `idx_org` (`org`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `test_organization` ( `organisation` varchar(255) NOT NULL, `org-name` varchar(255) NOT NULL, PRIMARY KEY (`organisation`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `test_route` ( `sip` bigint(20) unsigned NOT NULL, `eip` bigint(20) unsigned NOT NULL, `origin` varchar(255) NOT NULL, PRIMARY KEY (`sip`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `test_aut_num` ( `aut-num` varchar(255) NOT NULL, `org` varchar(255) NOT NULL, PRIMARY KEY (`aut-num`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
sipおよびeipテーブルのフィールドは、範囲の先頭と末尾のip2longでデコードされたIPアドレスです。
データを解析するためのクラス:
<?php namespace Ripe; class Ripe { public $folder; public $time = 86400; function __construct($folder = '') { if (empty($folder)) { $folder = __DIR__ . '/../../config/ripe'; } if (!is_dir(__DIR__ . '/../../config/ripe')) { mkdir(__DIR__ . '/../../config/ripe', 0777, true); } $this->folder = $folder; } function needUpdate($file = '') { $current = time(); if ($current - filectime($this->folder . '/' . $file) > $this->time) { return true; } return false; } function download($url = '') { if (!empty($url) && true === $this->needUpdate($url) ) { system("cd " . realpath($this->folder) . " && wget ftp://ftp.ripe.net/ripe/dbase/split/" . $url . " && gunzip $url"); } } function read($file = '', $callback) { if (is_file($this->folder . '/' . $file)) { $f = fopen($this->folder . '/' . $file, 'r'); if (!empty($f)) { $string = []; while (($buffer = fgets($f)) !== false) {
データをブロックに書き込みます。つまり、ブロックを受け取り、すぐに書き留めました。 パフォーマンスを向上させるには、バッチでデータを挿入することをお勧めします。 組織データベースにダウンロードして書き込むためのコードは次のようになります。
$ripe->download('ripe.db.organisation.gz'); $ripe->read('ripe.db.organisation', function ($block, $file) { $ripeRoute = new \Ripe\RipeOrganization(); $ripeRoute->save($block); });
テーブル内のフィールドは、ファイル内と同じキーで入力されます。 フィールドを変更する必要がある場合、saveメソッドには「挿入前」ハンドラーがあり、これを使用してフィールドの名前を変更し、変更したものに書き込むことができます。
データ分析とサマリー表の取得。
データが受信されたので、判定自体がすでに合格するサマリーテーブルを作成できます。
CREATE TABLE `test_ripe` ( `sip` bigint(20) unsigned NOT NULL, `eip` bigint(20) unsigned NOT NULL, `org_code` varchar(100) NOT NULL, `org_name` varchar(255) NOT NULL, PRIMARY KEY (`sip`,`eip`), KEY `idx_org_name` (`org_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
今、最も簡単なことは残っています-必要なデータをファイナルテーブルに転送することです。
すべては、いくつかのリクエストによって決定されます。
select * from test_inetnum as t1 inner join test_organization as t2 on t1.org = t2.organisation; select * from test_route as t1 inner join test_aut_num as t2 on t1.origin = t2.`aut-num` inner join test_organization as t3 on t2.org = t3.organisation;
取得したデータはテーブルtest_ripeに入れられ、幸福になります。
結果
結果は私の期待を上回りました。 プロバイダーの定義は非常に正確に機能します(アドレスプールでテスト済み)。 また、素敵なボーナスは、
2ipよりもこのベースで定義がうまく機能すること
ですさて、実際には、次のクエリを使用して現在のテーブルからプロバイダーを決定できます。
SELECT * FROM `test_ripe` WHERE `sip` <= '33554435' AND `eip` >= '33554435' ORDER BY `eip` DESC LIMIT 1
ある範囲が別の範囲に含まれることが発生するため、リクエストのソートが必要です。