BitTorrent はファイル配信のためのプロトコルです。これは URL を使用してコンテンツを識別し、Web ネットワークとシームレスに統合されることを目的としています。単純な HTTP ダウンロードに対して、その利点は、複数のユーザーが同じファイルを同時にダウンロードする際に、これらのユーザー間でファイルのブロックを相互にアップロードできることにあります。複数のユーザーがファイル転送に参加することで、単一のファイルサーバーに依存することなく、大量のユーザーが同時にダウンロードをサポートでき、サーバーへの負荷が小さくなります。
BitTorrent ファイル配信は以下の要素で構成されています:#
- 通常の Web サーバー
- 静的なメタ情報ファイル
- BitTorrent トラッカー
- 原始ダウンローダー
- ウェブブラウザ
- BT ダウンロードクライアント
- ファイルは理想的な状況下で多くの最終ユーザーによって共有され、ダウンロードされることができます。
サービスを開始するには、ホストは以下の手順を実行する必要があります:#
- トラッカーを起動する(または既に実行中のものを使用する)。
- Apache などの通常の Web サーバーを起動する(または既に実行中のものを使用する)。
- 彼らの Web サーバー上で拡張子 .torrent を MIME タイプ application/x-bittorrent に関連付ける(または既にそうしている)。
- 提供するファイルとトラッカーの URL を使用してメタ情報 (.torrent) ファイルを生成する。
- メタ情報ファイルを Web サーバーに置く。
- 他のウェブページからメタ情報 (.torrent) ファイルにリンクする。
- 完全なソースファイルを持つダウンローダーを起動する。
ダウンロードを開始するには、ユーザーは以下の操作を実行します:#
- BitTorrent クライアントをインストールする。
- インターネットをサーフィンする。
- .torrent ファイルのリンクを開く。
- ローカルにファイルを保存する場所を選択するか、続行する部分ダウンロードを選択する。
- ダウンロードが完了するのを待つ。
- ダウンロードクライアントを終了する(終了指示を受けるまでアップロードを続けます)。
Bencode エンコーディング#
Bencode エンコーディングは、任意のデータ型の値をバイトストリームにシリアライズ(「直列化」とも呼ばれる)するために使用され、ネットワーク上で転送したりディスクに保存したりします。Bencode エンコーディングは、文字列、整数、リスト、辞書の 4 つの基本データ型をサポートしています。
- 文字列型の場合、長さプレフィックスとコロンの形式で表現されます。例えば「spam」は 4 とエンコードされます。
- 整数型の場合、文字「i」で始まり、その後に 10 進数表記の整数と文字「e」が続きます。例えば 3 は i3e とエンコードされ、-3 は i-3e とエンコードされます。
- リスト型の場合、文字「l」で始まり、その後にリスト内の各要素の Bencode エンコーディングが続き、最後に文字「e」で終了します。例えば [‘spam’, ‘eggs’] は l4:spam4 とエンコードされます。
- 辞書型の場合、文字「d」で始まり、その後にキーの ASCII コード順にソートされたキーと値のペアの B エンコーディングが続き、最後に文字「e」で終了します。例えば {‘cow’: ‘moo’, ‘spam’: ‘eggs’} は d3:cow3:moo4:spam4 とエンコードされます。すべての辞書型のキーは文字列でなければならず、元の文字列の順序でソートされる必要があります。
Bencode エンコーディングは、さまざまなデータ型のシリアライズおよびデシリアライズ操作に適したシンプルでコンパクトで可読性の高いデータシリアライズスキームを提供します。
メタ情報ファイル#
MetaInfo ファイル(.torrent ファイルとも呼ばれる)は、bencoding エンコーディングを使用した辞書で、以下のキーを含みます:
announce
トラッカーの URL アドレス。
info
このキーは、以下に説明するキーを含む辞書にマッピングされます。
テキストを含む .torrent ファイル内のすべての文字列は UTF-8 エンコーディングを使用する必要があります。
info 辞書#
BitTorrent がダウンロードファイル時に使用するメタデータ情報です。複数のキーと値のペアを含み、それぞれのキーは特定の属性を表します。例えば、推奨されるファイル名、ファイルブロックのサイズ、ハッシュ値などです。これらの属性は、クライアントがファイルを正しくダウンロードし、組み立てるのに役立ちます。
重要な属性のいくつかは次のとおりです:
- name:推奨されるファイル名で、純粋に提案のために提供され、強制力はありません。
- piece length:ファイルは固定サイズのブロックに分割され、この属性は各ブロックのサイズを指定します(通常は 2 の累乗)。
- pieces:各ブロックに対応するハッシュ値で、ファイルの完全性を検証するために使用されます。
- length:ファイルの長さ(単一ファイルの場合のみ)またはすべてのファイルを連結した総長です。
単一ファイルをダウンロードする場合は、name と length 属性のみを使用する必要があります。複数のファイルの場合は、files リストを使用してファイルのディレクトリ構造を表現し、各ファイルは length と path 属性を含む辞書で表されます。
トラッカー#
トラッカーの GET リクエストには以下のキーワードが含まれます:
info_hash:メタ情報ファイル内の info 値の bencoded 形式の 20 バイト SHA1 ハッシュ値。この値はほぼ確実にエスケープが必要です。これはメタ情報ファイルのサブストリングであることに注意してください。info-hash は .torrent ファイル内のエンコード形式のハッシュ値でなければならず、メタ情報ファイルを bencoded デコードし、info 辞書を抽出してそれをエンコードするのとまったく同じでなければなりません。bencoded エンコーディングが入力を完全に検証した場合(例えば、キーのソート、先頭のゼロの欠如など)、これを行う必要があります。そうでない場合、クライアントは無効なメタ情報ファイルを拒否するか、サブストリングを直接抽出する必要があります。無効なデータに対してデコード - エンコードの往復を実行することはできません。
peer_id:このダウンローダーの ID として使用される長さ 20 の文字列。各ダウンローダーは新しいダウンロードを開始する際に自分の ID をランダムに生成します。この値もほぼ確実にエスケープが必要です。
ip:オプションのパラメータで、このピアが存在する IP アドレス(または DNS 名)を指定します。通常はソースアドレスに使用され、ソースがトラッカーと同じコンピュータにある場合はこのパラメータを使用します。
port:このピアがリッスンしているポート番号。一般的な動作は、ダウンローダーがポート 6881 をリッスンしようとし、そのポートが使用中の場合は 6882、6883 などのポート番号を試み、6889 で放棄します。
uploaded:これまでにアップロードされた総量を 10 進数 ASCII コードで表します。
downloaded:これまでにダウンロードされた総量を 10 進数 ASCII コードで表します。
left:このピアがまだダウンロードする必要のあるバイト数を 10 進数 ASCII コードで表します。注意すべきは、これは downloaded とファイルの長さから計算できないことです。なぜなら、これはダウンロードの回復であり、ダウンロードされたデータの一部が完全性チェックを通過していない可能性があるため、再ダウンロードが必要です。
event:これはオプションのキーワードで、started、completed、または stopped(または存在しない場合は空)にマッピングされます。存在しない場合は、定期的な通知の 1 つです。ダウンロードが開始されたときは、started を使用して通知を送信します。ダウンロードが完了したときは、completed を使用して通知を送信します。ファイルが開始時に完了している場合は、completed を送信しません。ダウンローダーがダウンロードを停止すると、stopped を使用して通知を送信します。
トラッカーの応答は bencoded 辞書です。トラッカーの応答に failure reason キーワードが含まれている場合、そのキーワードは人間が読める文字列にマッピングされ、クエリが失敗した理由を説明します。他のキーワードは必要ありません。そうでない場合、interval という 2 つのキーワードを持つ必要があります。これは、ダウンローダーが定期的に再リクエストする間に待機すべき秒数にマッピングされ、peers はピアリストの辞書にマッピングされ、各辞書には peer id、ip、port の 3 つのキーワードが含まれ、ピアの自己選択 ID、IP アドレスまたは DNS 名、ポート番号を表します。イベントが発生したり、追加のピアが必要な場合、ダウンローダーは非定期的に再リクエストすることがあります。
より一般的には、トラッカーはピアリストの圧縮表現を返します。トラッカーがコンパクトなピアリストを返す場合を参照してください。
メタ情報ファイルやトラッカーのクエリに関して拡張を行いたい場合は、Bram Cohen と調整し、すべての拡張が互換性があることを確認してください。
通常、UDP トラッキングプロトコルを介して通知を行うこともできます。
ピアプロトコル#
BitTorrent のピアプロトコルは、TCP または uTorrent トランスポートプロトコルを介して動作します。BitTorrent では、ダウンローダーとアップローダーは対等であり、データはそれらの間で相互に流れることができます。データは多くの小さなブロックに分割され、複数のソースから同時にダウンロードされることで、ダウンロード速度と転送の信頼性が向上します。ダウンローダーがファイルのブロックのダウンロードを完了し、ハッシュ値が一致することを確認すると、そのブロックの情報をすべてのピアにブロードキャストします。
接続状態には 2 つのカテゴリがあります:ブロックまたは非ブロック;興味があるまたは興味がない。ブロックは、解除されるまでデータが送信されないことを意味します。データ転送は、一方が興味を持ち、他方がブロックされていない場合にのみ発生します。正しいデータ転送を実現するために、ダウンローダーは興味のある状態を維持し、適時更新する必要がありますが、ブロックされている場合でもです。データを転送する際、ダウンローダーは良好な TCP 性能を得るために複数のブロックのリクエストをキューに保持し、リクエストがすぐに TCP バッファに書き込まれない場合は、メモリ内にキューに保持して、ブロックが発生した際にすべてを破棄できるようにします。
ピアプロトコルは、ハンドシェイクプロセスと永遠に続く長さプレフィックスメッセージで構成されています。ハンドシェイクは 19(10 進数)文字で始まり、その後に「BitTorrent プロトコル」という文字列が続きます。2 つのノードを接続する前に、必要な情報を交換するためにハンドシェイクを行う必要があります。ハンドシェイクが開始されると、送信者は受信者に固定のハンドシェイクメッセージを送信します。このメッセージには、プロトコルバージョン、予約バイト、メタデータハッシュ値、ノード ID が含まれます。受信者はこれらの情報を検証し、それらが期待される値と一致するかどうかを確認します。一致しない場合、接続は切断されます。ハンドシェイクが成功すると、双方はデータの交換を開始します。データは一連の長さプレフィックスとメッセージを通じて転送されます。長さプレフィックスはそのメッセージの長さを示し、その後に実際のメッセージ内容が続きます。
ピアメッセージ#
すべての非アクティブメッセージは単一のバイトで始まり、以下にそのタイプを示します。
可能な値は次のとおりです:
- 0 – choke
- 1 – unchoke
- 2 – interested
- 3 – not interested
- 4 – have
- 5 – bitfield
- 6 – request
- 7 – piece
- 8 – cancel
‘choke’, ‘unchoke’, ‘interested’, および ‘not interested’ にはペイロードがありません。
bitfield メッセージ:このメッセージは最初のメッセージとしてのみ送信されます。そのペイロードはビットフィールドで、各ダウンローダーが送信するインデックスが 1 に設定され、残りのインデックスは 0 に設定されます。データを持たないダウンローダーはこの「bitfield」メッセージをスキップできます。ビットフィールドの最初のバイトはインデックス 0-7(上位ビットから下位ビットへ)に対応し、次に 8-15 というように続きます。末尾の余分なビットは 0 に設定されます。
have メッセージ:このメッセージのペイロードは単一の数字で、ダウンローダーが完了し、ハッシュ値を確認したインデックスを示します。
request メッセージ:このメッセージにはインデックス、オフセット、長さが含まれます。最後のパラメータは通常 2 の累乗であり、ファイルの末尾に達していない限りそうです。すべての現在の実装は 2^14(16 kiB)を使用し、この制限を超えるリクエストの接続を閉じます。
cancel メッセージ:リクエストメッセージと同じペイロードを持ちます。これらは通常、ダウンロードが終了したときにのみ送信され、「エンドゲームモード」と呼ばれる期間中に行われます。ダウンロードがほぼ完了したとき、最後の数部分は単一のホースモデム回線からダウンロードされる傾向があり、時間がかかります。最後の数ブロックが迅速に取得されるように、指定されたダウンローダーがまだ受け取っていないすべての部分のリクエストが現在保留中である場合、ダウンローダーはダウンロード中のすべての人にすべてのリクエストを送信します。これが非常に非効率的になるのを防ぐために、各作品が到着するたびに、他の人にキャンセルを送信します。
piece メッセージ:インデックス、開始、およびピースを含みます。これらはリクエストメッセージと暗黙的に関連しています。ブロックとキャンセルのメッセージが迅速に連続して送信される場合や、転送速度が非常に遅い場合、予期しないピースが発生する可能性があります。
まず、ダウンローダーは通常、ファイルの異なる部分をランダムにダウンロードし、特定のダウンローダーが他のダウンローダーのサブセットまたはスーパーセットを持つ状況を回避します。次に、各ダウンローダーが一貫したダウンロード速度を得られるように、アップロード速度を制限する操作(チョーキングとも呼ばれる)が必要です。このアルゴリズムは、ダウンローダー間で「目には目を」という戦略を使用して、安定したダウンロード速度を確保することを可能にします。最後に、現在使用されているチョーキングアルゴリズムは、異なるネットワーク環境で良好に機能する新しいアルゴリズムの重要性を強調しています。
まず、良好な TCP 性能を確保するために、アルゴリズムは同時にアップロードする接続数を制限する必要があります。次に、頻繁に choke と unchoke を行わないように、アルゴリズムはアップロード対象を安定して選択する必要があります。さらに、ある程度は自分のダウンロードを助けてくれたピアに報いるべきです。最後に、アルゴリズムは未使用の接続を利用してダウンロード速度を向上させることを試みるべきで、これを楽観的なアンチョークと呼びます。
現在展開されているチョーキングアルゴリズムは、これらの目標を達成するためにいくつかの措置を講じています。頻繁な変化を避けるために、アルゴリズムは 10 秒ごとにどのピアがチョークされるかを変更します。他の人に報いるために、アップロード接続の数を制限するために、アルゴリズムはダウンロード速度が最も良好で興味のある最初の 4 つのピアをアンチョークします。もし他のピアのアップロード速度が良好であるが興味がない場合、そのピアもアンチョークされる可能性があり、興味が突然生じた場合は、ダウンロード速度が最も悪いピアがチョークされます。もしダウンローダーがファイルを完全にダウンロードした場合、アップロード速度を使用してどのピアをアンチョークするかを決定します。
楽観的なアンチョークに関しては、アルゴリズムは 30 秒ごとに 1 つのピアを選択してアンチョークし、そのアップロード速度に関係なく(興味がある限りダウンローダーとしてカウントされます)。ローテーション中に、新しい接続は現在の楽観的なアンチョークの位置に 3 倍の確率で配置され、完全なデータブロックをアップロードする機会を十分に与えられます。