この記事で提供されるコードは完全ではないことをすぐに言わなければなりません。 使用されるプログラミング言語は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 { /** * @var string - RIPE */ public $folder; /** * @var int - , */ public $time = 86400; /** * Ripe constructor. * * @param string $folder */ 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; } /** * . * * @param string $file * * @return bool */ function needUpdate($file = '') { $current = time(); if ($current - filectime($this->folder . '/' . $file) > $this->time) { return true; } return false; } /** * . * * @param string $url */ 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"); } } /** * . * * @param string $file * @param $callback */ 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) { // if ("\n" != $buffer) { $string[] = trim($buffer); } else { $blockArray = []; // for ($i = 0; $i < $ic = count($string); $i++) { if (strpos($string[$i], ': ') === false) { break; } else { $arBlockData = explode(": ", $string[$i]); if (!empty($arBlockData)) { $key = trim($arBlockData[0]); $value = trim($arBlockData[1]); if (!empty($blockArray[$key])) { $blockArray[$key] .= $value . "\n"; } else { $blockArray[$key] = $value; } } } } // callback if (!empty($callback) && is_callable($callback) && !empty($blockArray) ) { call_user_func_array($callback, [ $blockArray, $file ]); } $string = ''; } } } } } }
データをブロックに書き込みます。つまり、ブロックを受け取り、すぐに書き留めました。 パフォーマンスを向上させるには、バッチでデータを挿入することをお勧めします。 組織データベースにダウンロードして書き込むためのコードは次のようになります。
$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
ある範囲が別の範囲に含まれることが発生するため、リクエストのソートが必要です。