スキップしてメイン コンテンツに移動

P2P探訪 Raider Torrentファイルを読み込んでみる(bencoding)

TorrentクローンをJava で作成しています。
そろそろ、Applet上で動作するデモができそうです。 試してみて解ったことが結構ありました。
そこで、学習したしことを、epub形式でまとめています。http://p.booklog.jp/users/kyorohiro


やる気スイッチが入らないので、書きかけの物をさらします。

-------------------------------------------------------------------

ダウンロードの始まり

データをダウンロードは、「へちまたん.torrent」といった、torrentを拡張子に持つファイルを取得することから始まります。

通常、インターネットを通じてWWWから取得することになると思います。
OSのイメージであれば配布しているサイトで手に入るかもしれません。 オープンソースアニメや著作権きれのデータなど、それ専用のデータを野止めているサイトを探すと良いでしょう。「オープンソース アニメ Torrent」、「著作権切れ Torrent」といったキーワードで検索してみてください。Googleで検索すれば簡単に見つかると思います。

このページでは、実際にTorrentファイルを読み込み。どのような情報が記載されているか調べてみましょう。

Bencode/Bencoding で書かれている

Torrentファイルはbencoding という形式で書かれています。  Torrentファイルを読み込むためには、bencodingを解釈できるようにならなくてなりません。 まずは、Bencodingを読み込んでみましょう。

String/Integer/List/Dictionaryを扱える

 bencodingは、 String/辞書/リスト の4つのデータ型を扱うことができます。
 そして、以下のようなフォーマットで書かれています。

  beninteger   : "i" [0-9]* "e"
  benstring    : [0-9]* ":" <bytes array/string> 
     # bytes array/string length is prev [0-9]*.
  bendiction   : "d" dictelements "e" 
  benlist      : "l" listelements "e"
  benobject    : beninteger | benstring | beniction | benlist
  listelements : benobject (benobject)*
  dictelements : benstring benobject (benstring benobject)*


ひとつひとつ見ていきましょう。
文字列
まずは文字列です。 この本ではbencodingでの文字列をbenstiringと呼ぶことにはます。 例えば、「torrent」という文字列は、こbenstringでは、「7:torrent」と書きます。  
また、benstringは  文字列だけでなく、バイト配列としても使われます。<20バイトの配列> は、「20:<20バイトの配列>」とあらわす事ができるのです。

整数
実数です。この本ではbencodingでの整数はbenintegerと呼ぶことにはます。例えば、「1024}という数字は、benintegerでは、[i1024e」と書くことができます。

リスト
リストとは、bencodingで扱えるデータ構造のひとつです。 0個以上のデータを順序ありでデータを保持できます。つまり、 文字、整数、リスト、辞書、を保持することができます。

この本ではbencodingでのリストはbenlistと呼ぶことにはます。
例えば、「512という数字と、"test"という文字列」は、benlistでは、[li512e4:teste」と書くことができます。                                                                                                                                           
辞書
辞書とはbencodingで扱えるデータ構造のひとつです。辞書データは文字列とデータを紐付けで管理することができます。
例えば RPGゲームで主人公のパラメータとして、名前、性別、レベル、得意な魔法、とか設定されているとします。辞書型は、主人公辞書は、"レベル"とキーを渡せば、主人公のレベルが返ります。 女の主人公ならば、"性別"とキーを渡せば、女性と返ります。

辞書です。この本ではbencodingでのリストはbendictと呼ぶことにはます。
例えば、bencodingで 「"レベル" 13」 「"magic" "halito"」 を持つ辞書は、bendictでは、[d5:levelei13e5:magic6:halitoe」と書くことができます。

パースしやすい構造になっている

bencodingはパースし易いつくりになっています。
先頭1文字で、どのデータ構造でできているかが判断できるようになっているからです。

例えば、 integerならば'i'、 stringならば's'、リストならば'l'、辞書ならば、'd' といった感じです。
なので、bencodingのdecoderは、以下のようなシナリオで実現できます。
1. 一文字読み込む。
2. どのデータか判別する。
3. データ形式に応じて読み込む。
4. 1に戻る。



今後の表記について

今後 bencodingでデーター構造を表はする場合は、以下の表記をしようします。
リスト
  「li512e4:teste」は、 「[ 512, test] 」と表記します。
辞書
  「d5:levelei13e5:magic6:halitoe」は「{level:13, magic:halito}」と表記します。

コメント

このブログの人気の投稿

KyoroStressの技術 -1- Low Memory Killer を意図的に発生させたい

[課題] Low Memory Killer を意図的に発生させたい Androidには、ヒープが涸渇すると使われていないアプリをKillする機能があります。 この記事では、意図的にヒープを枯渇させて、この状態をつくる方法について説明します。 単純にヒープを大量に消費するアプリを作成すれば良いように思えます。 しかし、これだけでは上手くいきません。   -A ひとつのアプリで消費できるヒープが制限されているため、ひとつのアプリで端末のヒープが涸渇している状態をつくれない。   -B ヒープを涸渇しているアプリがPFにKILLされる場合がある。 といった問題があります。 KyoroStressV2での解決方法を紹介します。 [KyoroStressでの解決方法] Kyoro Stress では、以下のような方法をとりました。 - 1. 複数のServiceを、各々異なるプロセスで起動する。 - 2. 各々Serviceで大量のヒープを消費する。 複数のプロセスを立ち上げれば、PFのヒープを枯渇させることができます。これで、(A)の問題が解決できました。 また、Bについては、「生きているプロセス」が「KILLされたプロセス」の分もヒープを消費すれば上手くいけそうです。 [BigEater(ヒープ消費サービス)の動作] KyoroStressV2で、ヒープを消費するサービスは以下のシナリオで動作しています。 - 1. 指定されたヒープを取得する。 is retry が true の時、指定されたヒープを取得できるまで、1を何度も繰り返す。 - 2. KILLされたサービスを復活させる。 is retry が true の時、Threadが死ぬまで、何度も2を繰り返す。 - 3. 終了 といった感じです。 このままでは、すべてのServiceがPFにKILLされたら上手くいかないように思うかも知れません。 しかし、時間がたつと(数秒)、PFはKILLしたServiceを再起動します。 このため、ServiceがすべてKILLされても、ヒープを大量に消費しようとする状態は保持されます。 [使い方] KyoroStressV2の操作方法…

P2P探訪 STUNでNAT越え その1

UPnPを用いて、NAT越えできました。しかし、ルータがUPnPをサポートしていなかったり。UPnPだけでは越えられないNATがあります。

本文では、その代案として前回解説できなかった。「適当なサーバーに接続してみて、相手から見えているアドレスを返してもらう方法」について解説していきます。

TCPの限界 インターネットで公開されている情報のほとんどは、TCPという通信方法でデータをやり取りされています。ですから、インターネットで情報を公開したい場合は、TCPサーバーを立ち上げる事を考える事でしょう。
 しかし、ルータがUPnPをサポートしていない場合、TCPを用いたサーバーを運用する事は困難になります。※ 基本、無理と考えもらって問題ありません。


接続相手から教えてもらう方法はどうした? 適当なサーバーに接続してみて、相手から見えているアドレスを返してもらう事で実現できないのでしょうか。前回はできそうな事を臭わせていました。しかし、TCPにおいて、これは困難です。

実際にTCPのプログラムを書き確認して見ましょう。接続相手のホストアドレスは推測できます。しかし、ポート番号を知るすべはありません。


import java.io.IOException; import java.net.Inet4Address; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; public class TCPTest { public static void main(String[] args) { TCPTest test = new TCPTest(); test.startServer(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } test.startClient(); } private Server mServer = new Server(); public void startServer() { mServer.start(); } public v…

P2P探訪 Raider その1-2 Torrentファイルフォーマット

というわけで、前回に引き続いて、この記事ではTorrentファイルについて説明します。 [Torrent file format] 前回、Bencodingを実装したのでTorremt Fileを読み込めることができるようになりました。 今回は、Torrentファイルから必要な情報を読み込む方法について解説します。 torretファイルから取得できる情報はどんなものかは、別の機会に解説します。 ここでは、torrentファイルには 2つのフォーマットがあることとデータ構造を説明します。 たとえば、「"announce"というデータが何なのか?」については解説しません。 torrentファイルでは、ダウンロード/アップロードの対象としているファイルが、ひとつの場合と複数の場合で構造がすこしだけことなります。 ひとつの時を、「single file」 複数の時を「multi file」と呼ぶことにます。 では、データ構造を紹介します。 - single file pattern bendiction benstring "announce" beninteger "creation date" bendiction "info" beninteger "length" benstring "name" beninteger "piece length" bebstring "pieces" - multi file pattern bendiction benstring "announce" beninteger "creation date" bendiction "info" benlist "files" bendiction beninteger "length" benlist "path" benstring be…