1. 第一章 はじめに
  2. 第二章 準備
  3. 第三章 関連研究
  4. 第四章 シミュレーションプログラム
  5. 第五章 今後の課題
  6. 第六章 まとめ
  7. 第七章 参考文献
  8. 第八章 付録

PAGE TOP

ns-3によるP4P活用プロトコルの実装

[初版作成日時] 2015/03/18
ネットワークシステム研究室 指導教員: 坂本 直志 教授 11EC054 鈴木 大和

第一章 はじめに

インターネットにおけるトラフィック量は年々増加しており、総務省の統計[2]によると平成25年11月における日本国内におけるブロードバンドサービス契約者の総ダウンロードトラヒックは平均約2.5Tbpsに到達した。これは前年同月比で35.6%も増加している。このうちP2Pが占める割合の増加は鈍化傾向にあるとはいえ、P2Pアプリケーションの一種であるBitTorrentのトラヒック量は依然として増加傾向にある。

P2P(Peer to Peer)とは従来のクライアント・サーバー方式とは異なり、全てのコンピュータがピアと呼ばれるクライアントにもサーバーにもなる形態で通信を行う方式のことである。このアーキテクチャを応用し、開発されたプロトコルやアプリケーションは数多く存在する。BitTorrentはそのうちの一つであり、Bram Cohen氏によって開発されたプロトコルとソフトウェアである[3]。

P2Pを活用したファイル配信ソフトウェアを利用するメリットの一つとして、トラフィックの一極集中を防げる点がある。これによりコンテンツの提供者側では、配信規模(ファイルサイズや配信相手の数)に応じたシステム増強に迫られることが無くなり、またユーザー側ではダウンロードが集中している人気コンテンツであっても高速ダウンロードすることが出来るメリットがある。しかし一方では膨大なトラフィックを生み出す原因になっている。また、そうして発生したトラフィックはコンテンツの提供者側で負担しない代わりに、ネットワークのバックボーンを提供するISP(Internet Service Provider)が一手に引き受けている状況にある。これはBitTorrentも例外ではない。

P2Pソフトウェアの利用により発生するトラフィックに対してISP(Internet Service Provider)は、少しでも負荷を減少させるべく、また、より公平なネットワーク利用を促すためにP2Pのトラフィックに制限を設けているのは周知の通りである。一方でP2Pソフトウェアにおいても、ISPの負荷を減らすべく非効率的なトラフィックの発生を減少させ、より効率的なファイル転送を実現するためにアルゴリズムが考案されている。

さて、P4P Working Groupが公開しているP4P: Explicit Communications for Cooperative Control Between P2P and Network Providersという論文がある[4]。この論文ではISPがP2Pに協力することで、より効率的なファイル転送を実現できるのでは無いか、と述べられている。

現在のP2Pアーキテクチャを採用するファイル配信アプリケーションは、アプリケーション上でオーバーレイ・ネットワークと呼ばれる面のネットワークを構築する仕組みになっている。すなわちファイル配信はオーバーレイ・ネットワーク上において行うのである。この仕組みにより、P2Pの特徴でもあるスケーラビリティや可用性が提供されている。しかしこのようなネットワーク利用は非効率的なファイル配信の原因にもなっている。これはオーバーレイ・ネットワークがネットワークトポロジーを考慮しない点、またネットワークトポロジーをP2Pアプリケーションのあるエンド間の努力だけで調査するには限界があることに起因する。

例えばMPLSのような新技術や測定プローブに応答しないルーターの存在はネットワーク・トポロジーの構造を調べる上で非常に困難である。また利用可能な帯域やパケット損失レートの測定も困難であり、さらにはIPトランジットのようなコストの掛かる経路や、ネットワーク利用のポリシーを知るに至っては不可能に近い。

つまりこうした末端のピアの努力では測り知る事の出来ない情報をISPが積極的に提供することで、より公平で効率的なネットワーク利用を促そうと提案されているのがP4P(Proactive network Provider Participation for P2P / Provider Portal for P2P)と呼ばれる技術である。この技術を活用することで、オーバーレイ・ネットワークの構築に当たってエンド間で計測可能な性能情報のみならず、ネットワーク・トポロジーや利用に際してのポリシーなどを考慮することが可能となる。この技術を活用するインセンティブはISPのみならず、P2Pアプリケーションのユーザーにもある。例えば、より効率的なネットワーク利用が出来ることで、いっそう高速なファイル配信が可能になる期待がある。またISPと良好な関係を築けることで帯域制限を掛けられる可能性を減らせると考えられる。

とはいえP4Pはあくまで情報提供する技術であり、「提供された技術をどのように活用するのか」ということが重要になる。P4Pを活用したアルゴリズムは既にいくつか考案されている。

例えば、魏氏が提案する「P2Pトラフィックの効率的制御法」ではAS番号を利用し、出来る限り発生する通信を同一AS内に閉じ込める、というアプローチがとられている[5]。また本研究室の村松氏が提案する、「遠方優先アルゴリズム」では、各ピアの近くにファイルを持ったピアが存在するようにファイルを拡散させる、といったアプローチがとられている[6]。そして今泉氏らによって提案されている「ホップ数重み付き応答遅延に基づくノード選択法」では通信速度とISPのホップ数の両方を考慮したアプローチがとられている[8]。このように提案されているアルゴリズムはそれぞれ提案者によって特性の評価が行われている。評価方法は実際に複数のコンピュータを使ったBitTorrentネットワークの構築や、Javaを用いた独自シミュレータの作成である。しかしいずれにおいても現実のネットワークに則した複雑な構造やパラメータの、そして規模の大きなネットワーク環境下での特性を検証するには至っていない。

こうした背景において、本研究ではより詳細なP4P活用アルゴリズムの特性解析を行うことを目的に行う。そして前述の特性解析の困難さに対してns-3と呼ばれるネットワークシミュレータを用いることで解決に当たった。

ns-3とは離散イベント駆動型のネットワークシミュレータである。これは米国DARPAの研究プロジェクトの研究成果であるNetwork Simulator 2の後継であり、開発に当たっては著名な大学や研究機関が関わっている[1]。また、GNU GPLv2のライセンスに基づくフリーソフトウェアであり、研究や開発などの目的で使用されている。ns-3では様々なレイヤーにパラメータを与えてシミュレーションを行うことが可能であり、例えばWi-Fi接続下における端末の移動の影響の解析からTCPプロトコルにおけるwindowサイズの変化の測定、さらにはns-3のシミュレータ上に配置する端末にインストールさせるアプリケーションの開発も行える。各接続に対して帯域や、エラーレートの設定も可能である。またpcap形式によりログを出力することも出来るのでWiresharkによる通信内容の分析が出来る。当然、ユーザーが独自に出力方法を定義することも可能である。このように多数のパラメータを考慮しながらも、容易に分析できるのはもちろんのこと、大規模シミュレーション評価をより簡単にするツールも用意されており、P2Pの特性を解析するに向いているといえる。

本研究はns3上にP2Pアプリケーションの一つであるBitTorrentのアプリケーションモデルを実装すること、そしてBitTorrentを動作させる基本的なアルゴリズムを実装し、またP4Pを活用したアルゴリズムの実装を行い双方の特性を解析、比較することを目標に行う。結果的には実装したBitTorrentアプリケーションの不都合を完全に取り除くまでに至らなかった為、本稿では実装の進捗状況の報告となる。

本稿の構成は、第二章で背景となる用語の紹介など準備を行い、第三章で関連研究を示す。続く第四章で研究内容であるシミュレーションプログラムを示し、第五章で今後の課題を述べる。最後に第六章でまとめる。

第二章 準備

ns-3について

ns-3は離散イベント駆動型のネットワークシミュレータのことである[1]。これは米国DARPAの研究プロジェクトの研究成果であるNetwork Simulator 2(ns-2)の後継であり、開発には著名な大学や研究機関が関わっている。

ns-3によるネットワークシミュレーションでは、主に二つのファイルを記述していくことになる。一つは、ネットワーク機器の定義、接続、設定、そして動作のスケジュールを定義するシナリオファイル。もう一つは、プロトコルや、それを支えるアルゴリズムを定義するモジュールファイルである。ただし、有名なプロトコルの多くはns-3標準で用意されているので、新規にモジュールを作成する必要は無い。

シナリオファイルでは、構築したいネットワークの構成とプロトコルスタックのすべてを自分の手で書いていく。具体的には下位層ではノードと呼ばれる通信デバイスの筐体を用意し、そこにNICを装着する。NICには有線もしくは無線デバイスが存在し、それぞれ適する形で接続を行う必要がある。つまり、どのデバイス同士を有線で接続するか、また無線であればどういったSSIDを割り当てるか等といった設定を行う。下位層の設定をした次はIPアドレスの割り振りやルーティングプロトコルの設定、トランスポート層で用いるプロトコルなどの設定を行う。実際にルーティングプロトコルを流すことも出来るが、予め各ノードが完成したルーティングテーブルを持っている状態でシミュレーションを開始することが出来る。最後に、ネットワークシミュレーションに使うアプリケーションをインストールする。これらの作業を一つ一つ行うのは煩雑なので、ns-3では様々なHelperと呼ばれるクラスとモジュール群が用意されている。

以下に、ns-3付属しているサンプルファイルと概説を示す。サンプルファイルは「ns-3.xx/examples/tutorial/second.cc」にあり、これはシナリオファイルである。

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

// 必要なファイルをインクルードする(APIドキュメントなどを参照)
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/ipv4-global-routing-helper.h"

// Default Network Topology
//
//       10.1.1.0
// n0 -------------- n1   n2   n3   n4
//    point-to-point  |    |    |    |
//                    ================
//                      LAN 10.1.2.0


using namespace ns3;

// シナリオファイル内で記述するログについての構成
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");

int 
main (int argc, char *argv[])
{
  // コマンドライン引数に関する設定
  bool verbose = true;
  uint32_t nCsma = 3;

  CommandLine cmd;
  cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
  cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);

  cmd.Parse (argc,argv);

  if (verbose)
    {
      LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
      LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
    }

  nCsma = nCsma == 0 ? 1 : nCsma;

  // Step 1. Point-to-Point接続で使用するノードを作成する(未接続)
  NodeContainer p2pNodes;
  p2pNodes.Create (2);

  // Step 2. LANケーブルで接続するノードを作成する(未接続)
  NodeContainer csmaNodes;
  csmaNodes.Add (p2pNodes.Get (1));
  csmaNodes.Create (nCsma);

  // Step 3. Point-to-Pointによる接続の設定
  PointToPointHelper pointToPoint;
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

  // Step 4. Point-to-Pointで接続する(NICのインストール)
  NetDeviceContainer p2pDevices;
  p2pDevices = pointToPoint.Install (p2pNodes);

  // Step 5. LANケーブルによる接続の設定
  CsmaHelper csma;
  csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
  csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));

  // Step 6. LANケーブルで接続する(NICのインストール)
  NetDeviceContainer csmaDevices;
  csmaDevices = csma.Install (csmaNodes);

  // Step 7. 全ノードにプロトコルスタックをインストールする
  InternetStackHelper stack;
  stack.Install (p2pNodes.Get (0));
  stack.Install (csmaNodes);

  // Step 8. NICに対してIPアドレスを割り当てる
  Ipv4AddressHelper address;
  address.SetBase ("10.1.1.0", "255.255.255.0");
  Ipv4InterfaceContainer p2pInterfaces;
  p2pInterfaces = address.Assign (p2pDevices);

  address.SetBase ("10.1.2.0", "255.255.255.0");
  Ipv4InterfaceContainer csmaInterfaces;
  csmaInterfaces = address.Assign (csmaDevices);

  // Step 9. アプリケーションの構築(UDP Echo サーバー)
  UdpEchoServerHelper echoServer (9);

  ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
  serverApps.Start (Seconds (1.0));
  serverApps.Stop (Seconds (10.0));

  // Step 10. アプリケーションの構築(UDP Echo クライアント)
  UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
  echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
  echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
  echoClient.SetAttribute ("PacketSize", UintegerValue (1024));

  ApplicationContainer clientApps = echoClient.Install (p2pNodes.Get (0));
  clientApps.Start (Seconds (2.0));
  clientApps.Stop (Seconds (10.0));

  // Step 11. ルーティングテーブルの作成
  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

  // Step 12. ログの出力方法について設定
  pointToPoint.EnablePcapAll ("second");
  csma.EnablePcap ("second", csmaDevices.Get (1), true);

  // Step 13. シミュレーションの開始と終了
  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}

図2-1. サンプルプログラム「ns-3.21/examples/tutorial/seconds.cc」

このプログラムで作成されるネットワークは、Point-to-Point接続による2つのノードとLANケーブルによる4つのノードの接続である。アスキーアートによるネットワーク図が参考になる。

  1. 冒頭

    1行目の記述はEmacsで整形を行うための記述である。その後はライセンス表記、ファイルのインクルード、ネットワークトポロジーのアスキーアートと続く。ns-3に付属しているサンプルファイルではこのようにアスキーアートによってネットワークトポロジーを示しているものが多い。インクルードするファイルはAPIドキュメントに記述されているのでそれを参考にする。ns-3のクラス、関数はns3名前空間の中にあるので、予め名前空間の使用を宣言しておくと以降の記述が楽になる。

    さて、ns3では標準エラー出力にログを出力することが出来る。しかしネットワーク機器が増えるほどにログの量が膨大になり、欲しいログを得ることが困難になる。そこで、ns3ではNS_LOGというマクロを用いてログの出力を制御する。これによりログを出力するか否か、またログレベルをどうするのか、シナリオファイル側で一括して制御することが出来る。シナリオファイルに対してもログの出力内容を構成することが出来るのでNS_LOG_COMPONENT_DEFINEというマクロが使用されている。

    続いてmain関数の中に入るとコマンドライン引数に関する設定がある。これを利用することでシミュレーション毎にシナリオファイルを書き直さなくてもコマンドライン引数によってパラメータを変更することが出来る。このサンプルではログ出力をするか否か、またLANで接続するノード数を制御することが出来る。(以降の説明では引数は無かったものとして扱う。)

    引数のパース後にあるLogComponentEnable(char *const name, enum LogLevel level)という記述で、標準エラー出力されるログの内容を制御している。nameはNS_LOG_COMPONENT_DEFINEで定義した内容に対応する。調べたい部分のログレベルを低く、その他はログレベルを高く、もしくは出力しないよう設定することで調査が容易になる。

  2. ネットワークトポロジーの定義

    ネットワーク機器の作成と接続の作成を行う。この作業で注目すべきはNodeとChannelと呼ばれる概念である。Nodeとはすべてのコンピュータデバイス(筐体)をまとめた概念である。ns-3ではns3::Nodeクラスとして抽象化し、提供している。すなわちNodeオブジェクトを作成することで一つのネットワーク機器が作成される。また、Nodeには管理用のユニークな32bit長符号無し整数のIDが自動的に割り振られる。作成順に1から昇順に割り振られ、デフォルトではこのIDをプリフィックスとして各ノードのイベントトレースファイルが出力される。(ただし、IDで機器を管理するのはわかりにくいのでユーザーが独自に名前を定義することが出来る)

    一方、Channelとは各Node間の接続の概念である。Nodeと同様にns3::Channelクラスが提供されている。しかしこのクラスは抽象クラスなので、これを継承した(例えばns3::PointToPointChannel、ns3::CsmaChannelといった)クラスのオブジェクトを作成して接続を設定する。

    つまりネットワークトポロジーの定義はNodeを作成し、その間をChannelで結ぶ作業となる。しかし、この設定を一つ一つ行うのは、小規模ネットワークであればともかく、ある程度以上の規模になると非常に煩雑な作業になる。そこでns-3にはこうした設定を容易に行うためのHelperと呼ばれる補助機能を持つクラスを用意している。このHelperはContainerというポインタの集合クラスと共に用いることで一括して設定を行う機能など、ネットワークトポロジーを容易に構築するための機能を提供する。

    複数のns3::Nodeを管理するためにはns3::NodeContainerと呼ばれるns3::Nodeのポインタの集合を管理するクラスによって行う。ネットワークには常に複数のns3::Nodeが存在するので通常はこれを用いてNodeの生成や管理を行うので直接Nodeオブジェクト管理する必要は少ない。また、このns3::NodeContainerを単位としてHelperクラスを適用することで、一括設定することが出来る。(注: Helperは各モジュール毎に独立に用意されるもので、共通の抽象クラスを継承しているわけではない。)

    この作業は先に示したSecond.ccのStep 1〜Step 6に対応する。

    まずStep 1とStep 2ではNodeContainerを使用してノードの生成を行っている。Step 1ではPoint-to-Pointで接続する2つのノードを生成、Step 2ではPoint-to-Point接続とLAN接続の両方を行うノードを追加してから、LANのみで接続するノードを生成している。作成したNodeの集合はそれぞれp2pNodesとcsmaNodesという変数(NodeContainerオブジェクト)に入れる。

    Step 3ではPoint-to-Point接続に関する設定を行うためにPointToPointHelperオブジェクトを作成する。そしてStep 4でp2pNodesに含まれているNodeに対してまとめてPoint-to-Point接続する。この作業はNodeという筐体ににPoint-to-Point接続に対応したNICを差し込むイメージである。接続するためにHelperによって作成されたPointToPoint接続用のNetDeviceの集合を管理するためにp2pDevicesという変数(NetDeviceContainerオブジェクト)に入れる。

    Step 5ではLAN接続(CSMA/CD)に関する設定を行うためにCsmaHelperオブジェクトを作成する。そしてStep 6でcsmaNodesに含まれるNodeに対してまとめてLAN接続する。この作業はNodeという筐体にLAN接続に対応したNICを差し込むイメージである。接続するためにHelperによって作成されたCSMA/CD接続用のNetDeviceの集合を管理するためにcsmaDevicesという変数(NetDeviceContainerオブジェクト)に入れる。

    NodeとNodeContainerの関係と同様に、NICに対してもNetDeviceとNetDeviceContainerの関係がある。後半IPアドレスの割り振りを行う際にNetDeviceContainerオブジェクトが必要となるために、ここで変数を作成している。

    上記で行った設定の通り、Helperクラスには大抵xxxAttributeと呼ばれる関数が用意されており、これを通して各種設定をすることが出来る。

  3. プロトコルスタックの実装

    次にStep 7でIPv4/IPv6/TCP/UDPといったプロトコルスタックをインストールする。

  4. IPアドレスの割り振り

    IPアドレスはNode単位では無くNetDevice単位で行う。先に作っていたNetDeviceContainer変数とIpv4AddressHelperを組み合わせることで容易に割り振りすることが出来る。SetBase関数でネットワークアドレスとサブネットマスクを指定し、Assign関数によって若い番号から順番にNICに対してIPアドレスが自動的に割り振られる。この作業はStep 8に対応する。

  5. アプリケーションの構築

    サンプルのStep 9とStep 10に対応する。このサンプルではns-3に標準で組み込まれているアプリケーションをインストールしている。IPアドレスの割り振りと同様、Helperクラスが用意されているので容易に設定することが出来る。インストール済みのアプリケーションはApplicationContainerでまとめて管理することが出来、これを用いて一括でシミュレーションの開始時間、終了時間を設定する。ここでもxxxAttribute関数を用いて一括設定していることがわかる。

  6. ルーティング

    ここまでの作業でネットワークの構築作業は終わったが、ルーティングテーブルを持っていない為にNodeは他のネットワークのNodeと通信をすることが出来ない。そこでStep 11のように書くことで、すべてのNodeに対してルーティングデータベースとルーティングテーブルを組み込む。これにより、すべてのNodeがOSPFプロトコルによってルーティングテーブルを得た状態と同等になる。

  7. イベントトレースファイルの出力

    ns-3では標準エラー出力に対して出力するログとは別に、NIC毎に通信内容をイベントトレースファイルとして出力することが出来る。この設定はStep 12に対応する。Channelを作成するときに用いたHelperオブジェクト(厳密には、ns3::PcapHelperForDeviceまたはns3::AsciiTraceHelperForDeviceを継承しているHelper)を用いて設定を行うことが出来る。pcapファイルであれば[Name]-[NodeID]-[NetDeviceID].pcapといった形式でファイルが出力される。pcap形式はtcpdumpもしくはwiresharkなどで内容を確認することが出来る。またHelperに対する設定でプロミスキャス・モードでロギングするか、否かを選択することも出来る。

  8. シミュレーションの開始と終了処理

    最後にシミュレーションの開始と終了処理を記述する。Step 13に対応する。

以上がシナリオファイル記述の流れになる。シミュレーションするには「ns-3.xx/scratch」ディレクトリにファイルを移し、ns-3のホームディレクトリから以下のコマンドを実行する。拡張子は記述しないことに注意する。 イベントトレースファイルはns-3のホームディレクトリに出力される。出力された各種ログデータはGnuplotなどで可視化することで視覚的な分析を行うことが出来る。

#シミュレーションを実行
$ ./waf --run scratch/second

#引数を付けてシミュレーションを実行
$ ./waf --run "scratch/second --nCsma=4"

#標準エラー出力の内容をファイルに書き出す
$ ./waf --run scratch/second > log.out 2>&1

図2-2. シミュレーションの実行方法

本研究ではモデルを一から開発しており、またhelperクラスの開発まで至っていないので殆どを手動で設定している。モデルファイルの記述、利用方法は以下の通りである。

  1. 必要ファイルの生成

    ns-3付属のcreate-module.pyを利用して新規に作成するモジュール用のテンプレートファイルを記述する。これによりns-3.xx/src以下にディレクトリが作成される。生成されるファイル(ディレクトリ)はサンプルスクリプトを格納するexample/、helperを格納するhelper/、モジュール本体であるmodel/、テストスクリプトを格納するtest/、そしてモジュールを構成するwscriptファイルである。

  2. wscriptの編集

    自動生成されたファイルのみで完結する場合は必要ないが、モジュール内でファイルの分割を行う場合に編集が必要となる。ns-3が用いるwafと呼ばれるビルドシステムではwscriptと呼ばれるpythonで記述されたスクリプトファイルで対象ファイルの管理を行っている。よってモジュール内でクラスの分割を行う場合はwscriptに新規ファイルの情報を追加する必要がある。

  3. モデルファイルの書き方

    付属のサンプルファイル、およびAPIドキュメントを参考に行う。APIドキュメントはns-3公式サイトでも閲覧することが出来るが、Doxygenでソースコードをコンパイルしてローカル環境に置いておくと作業効率が良い。(ドキュメントは数GBのファイルになる)

    本研究ではアプリケーション層の新規モジュール開発を行ったが、アプリケーションを開発する場合はモジュールに対してns3::Applicationを継承することでアプリケーションとしての基本的な機能が実装される。通信にはソケットプログラミングと同等の手順で行える。ただし、プログラミング時に留意すべき点としてSocketプログラミングにおいてブロッキングで受信を待ち受けることは出来ない。これはns-3が離散イベント駆動型で、イベントが発生する毎に時間を止めてイベントを処理するからである。

    シミュレータの動作イメージ図
    図2-3. シミュレータの動作イメージ

    つまり無限ループ回す、ブロッキングにてデータを待ち受けたところで、シミュレータ上での時間は一向に経過しないのでデータは永久に来ることがなく、シミュレータのハングアップに繋がる。

    ハングアップするプログラム
    図2-4. ハングアップするプログラム

    よって、Socketプログラミングでは非ブロッキングによるプログラミングをする必要がある。具体的には、データが通信の待ち受けバッファーに到着したときに呼び出される関数を定義する。そして、コールバックされる毎にデータが完全な状態か(処理可能なだけデータを受信しているか)をチェックし、完全な状態になったら具体的な処理を行う。また受信したデータに対する処理を行った場合、受信バッファから該当する分だけ削除する。これを繰り返すことでアプリケーションを作成する。

    コールバックを使ったプログラム
    図2-5. コールバックを使ったプログラム

    またデータの受信のみならず、各イベントの処理中は時間が止まっていることに十分留意すべきである。受信したデータに対する処理時間は意識せずにコードを書いた場合0[ns]で実行されたことと同等として扱われる。処理時間を意識しないプログラミングはシミュレータのハングアップに繋がるので、特にループ処理を記述する際には十分注意する必要がある。必要である場合には処理時間を経過させるns3::Simulator::Schedule()関数によるイベントのスケジューリングをする必要がある。この仕組みを用いることで、処理時間を考慮したループ処理や、指定時間経過後に処理を行うことが出来る。

  4. Helperクラスの作成

    それなりの規模のシミュレーションを行うのであればHelperクラスも作成すべきである。アプリケーションモジュールの開発であれば、例えばns3::NodeContainerに含まれるすべてのns3::Nodeオブジェクトに対してインストール作業を行う関数の作成などが考えられる。このクラスを適切に作成することで、シナリオファイルの記述が非常に容易になる。

  5. 利用

    Build-inのモデルと同様、シナリオファイルにおいてインクルードすれば良い。Helperクラスを作成していない場合は手動でインストール作業を行う必要がある。(特にHelperクラスを用意しない場合、シナリオファイルにおいてもポインタを意識したプログラミングをする必要があるので、モジュールの開発者とシナリオファイルを記述する人が別である場合に少々厄介な事になると思われる。とはいえ生のポインタを扱う必要は無く、ns3::Ptr<T>と呼ばれるboost::intrusive_ptrと同等のスマートポインタで安全に扱える。)

最後に、ns-3の導入及び利用方法は公式サイトが用意しているns-3 tutorialが最も参考になる。また、導入手順に躓いた際はns3-tutorialにリンクが記載されているWikiが最も詳しく、様々なプラットフォームに対応した、インストールのHow toが記載されている。

ところで、ns-2ではシミュレーションの記述言語としてOTCLが用いられていたが、ns-3になりC++(及びPython)でシミュレーションを記述するようになった。そのためns-2とns-3では互換性が無い。一方でC++が採用されたことで学習コストが低くなり、大規模シミュレーションが容易になったとされている。

P2Pとは

P2Pとは従来のクライアント&サーバー方式とは異なり、すべてのコンピュータがピアと呼ばれるクライアントにもサーバーにもなる形態で通信を行う方式のことである。

HTTPに代表されるクライアント&サーバー方式とは、多数のクライアントに対して一台のサーバー、もしくは少数のサーバー群によって処理が行われる方式のことである。この方式ではトラフィックがサーバー側に集中することや、コンテンツの需給に併せてサーバーや回線を調達する必要があり、同一ファイルを大勢に配布するにはサービスの提供者とって多大なコストが掛かる方式である。ただし最も普及ていることや、利用者にスキルを求めない点で今日においても一般的に使われている。

クライアント&サーバー方式のファイル配信例
図2-6. クライアント&サーバー方式のファイル配信例

一方P2P方式とは全てのコンピュータが対等にファイルの交換を行う方式のことである。この方式ではトラフィックが一部分に偏らないメリットがある。また仕組み上、コンテンツの需給に応じてP2Pのネットワークシステムもスケーリングされる。すなわち、同一のファイルを大勢に配布するのに一般的なコンピュータのみで実現でき、かつ利用者が多いほど効率が上がるというメリットがある。一方で利用には専用のソフトウェアを導入する必要やファイアウォールやルータの設定によっては通信が出来ないことがあるため利用に際して一定のスキルが求められることもある。(補足1)

P2P方式のファイル配信例
図2-7. P2P方式のファイル配信例

しかしこの仕組みは、コンテンツ配信者にとってコストが減少するが、それはトラフィックが偏在しにくからである。むしろネットワーク全体で見ると、P2Pネットワークの維持に掛かる通信分や、非効率的な通信が発生することで余分なコストを支払っているのでは無いかと考えられている。これはクライアント&サーバー方式に比べてネットワークの利用予測が立てづらく、またオンデマンドではなく大量のコンテンツの集まりが送受信される事があるためである。

またファイルの転送経路がネットワークトポロジーで最適化されるのでは無くピア独自の運用方法(大抵はダウンロード速度)によって選択される。そのために、同一AS内でファイル転送すれば発生しないトランジット通信が無駄に発生するなどの、運用コストの増加を引き起こすと思われている。

以上の理由から、ISP(Internet Service Provider)からはP2P通信の負担を嫌い、通信規制を掛けられることが多い。

補足1)一般的に「NAT(NAPT)越え」と呼ばれている問題。通常、端末にグローバルIPアドレスが振られることは珍しくブロードバンドルーターをゲートウェイとしてプライベートIPアドレスを振って利用する事が多い。この場合、ゲートウェイ内部の端末が外部へセッションを張るときにNAPTと呼ばれるアドレス変換機能によってプライベートIPアドレスからグローバルIPアドレスの変換が行われる。またこの時、同時にポート番号の変換も行われ、その内容はNAPTテーブルに記録される。これにより、外部から内部への戻りの通信であっても誰宛であるのかを一意に特定、転送することが出来る。しかしP2Pのように外部からセッションを開始することがある場合、その通信はNAPTテーブルに記録が無いため転送先がわからず、端末まで通信が到達出来ない問題が生じる。これを防ぐためにはアプリケーション側で何らかのNAT越え技術を採用したり、ユーザーがポートフォワーディングと呼ばれる、特定ポート宛ての通信を決められた端末に転送する、という設定を予め行う必要がある。しかしこの設定は初心者にとって決して容易な物では無く、大きな負担になる。

BitTorrentプロトコルの概要

BitTorrent[3]はハイブリットP2P型に類する。すなわち、ピアの検索はTrackerサーバーと呼ばれるHTTPサーバーに任せるが、データの転送はピア同士で行うというものである。(オプションでDHTを用いたネットワーク構築を行うことは可能)

ファイル共有ネットワークに参加するにはMetainfoファイル(*.bittorrentファイル)と呼ばれるデータを予め入手する必要がある。このファイルにはダウンロードしたいファイルのメタ情報(長さ、ハッシュ値など)とTrackerサーバーのURLが含まれている。この情報を基にしてTrackerサーバーにアクセスし、他のネットワーク参加者であるピア情報のリストの取得をすると同時に、ネットワークに参加する事をTrackerサーバーに登録する。

Trackerサーバーからピア情報のリストをダウンロードすると、この情報を元にして他のピアに対してコネクションを行う。ピアとのコネクションに成功すると互いにHandshakeと呼ばれるメッセージを送信し、成功することでお互いファイル転送を行う準備が整う。Handshake後はBitfieldと呼ばれるメッセージを送信することで、お互いにファイルダウンロードの進捗状況を教える。

Handshakeが完了した時点ではまだファイルの転送は行えない。BitTorrentのクライアントはピア同士でChoke-Unchokeと呼ばれる状態を持っている。Handshakeの完了直後はChokeと呼ばれる状態で、これは相手ピアからファイル転送の許可が下りていない状態を表す。そのためファイルのアップロードをする意思があるピアは相手にUnchokeメッセージを送信し、ファイル転送許可を与えることを相手に伝える必要がある。このUnchokeするピアをどれにするのか、いつ行うのか、といった事がファイル転送を効率的にするための肝となる。

一方で相手に出したファイル転送許可を取り消すことも出来る。これはChokeメッセージを送信することで実現している。このChokeメッセージを出すタイミングは各BitTorrentクライアントの実装に任されているが、通常はファイル転送を行なわないピアや転送速度の遅いピアをChokeする。

転送許可が下りた後にどのピース(ファイルの断片)を要求するのか、というのにも戦略がある。BitTorrentではファイルはピースと呼ばれる(EOF前のピースを除く)固定長のブロックに分割したデータでやりとりを行っている。ピース単位でやりとりを行うことでファイルのダウンロード途中であってもアップロードが行える。しかし全てのピースがネットワークに等しく分布している訳では無い。そこでネットワーク上に偏在するピースの希少価値等を参考にしてどのピースを要求するか、といった事を考える。

すなわちファイルのアップロードを適切に行わなければ自身もファイルのダウンロードが上手く進まないというジレンマによって、BitTorrentのネットワークの円滑なファイル交換システムは支えられているといえる。こうしたアルゴリズムの事を一般にUnchokeアルゴリズム、Chokeアルゴリズム、そしてピース選択アルゴリズムと呼んでいる。

  1. Trackerサーバーとの通信

    Metainfoファイルに記述されているTrackerサーバーの情報もとに、Trackerサーバーへ接続、自身の情報をTrackerサーバーに登録する。同時に他のピアの情報をTrackerサーバーから受け取る。

  2. 他のピアへの接続

    Trackerサーバーから受け取ったピアリストを参照し、他のピアへの接続を試みる。

  3. ChokeとUnchoke

    接続したピアノ中からアルゴリズムによってUnchokeするピアを選択、相手に通知する。これによりUnchokeされたピアはファイル要求をすることが出来るようになる。

    ※接続直後はChoke状態である

表2-1. 一般的なBitTorrentアプリケーションに実装されるChoke&Unchokeアルゴリズム
アルゴリズム名概要
基本的なChokeアルゴリズム一定数(通常4つ)のピアに対してアップロードを許可する。どのピアをUnchoke状態にするかは現在のピアのダウンロード速度によって決定する。
楽天的なUnchoke戦略30[s]毎にChoke状態にしているピアの中から順々にUnchokeする戦略。単純にダウンロード速度だけを元に決定するアルゴリズムのみを運用すると一部のピアに対して最適化する可能性がある為、それを回避するための戦略。通常は4つあるUnchokeピアの内、一つのピアにはこのアルゴリズムによって選ばれる。
反冷遇主義戦略そのピアに対してアップロードしているにもかかわらず、ファイルのダウンロードが出来ない場合、冷遇されていると見なしてChoke状態にする。また、代わりのピアを楽天的なUnchoke戦略で見つけ出す。冷遇したピアには今後Unchoke状態にしないようにする。
アップロード・オンリーファイルのダウンロードが完了したピアが取る戦略。アップロード速度のみに基づいてUnchokeするピアの選択を行う。
表2-2. 一般的なBitTorrentアプリケーションに実装されるピース選択アルゴリズム
アルゴリズム名概要
集中戦略一つのピースを複数のサブピースとして分割し、複数のピアから同時に一つのピースのダウンロードを行う戦略。
優先戦略流通量の少ないピースを優先的にダウンロードする戦略。このアルゴリズムによって異なるネットワーク上の流通量を平滑化し、同時に分散させていく。ピースが取得できなくなることを防ぐ意味もある。
ランダム戦略起動直後は完全ランダムでダウンロードするピースを選択する。
End Game モデルダウンロードの最終段階において、一斉に複数のピアからダウンロードを行う戦略。これによりピアを素早くSeeder(完全ファイルを持つピア)状態にする。

P4P(Proactive network Provider Participation for P2P)

P4P(Proactive network Provider Participation for P2P / Provider Portal for P2P)[4]とよばれる技術はISP(Internet Service Provider)がP2Pクライアントに情報提供することでネットワーク負荷を軽減させることを目的に提案されている技術のことである。

現在のP2Pクライアントは既存のネットワーク上に「オーバーレイネットワーク」と呼ばれるアプリケーション上での論理的なネットワークを構築する。これにより実際のネットワーク構造に左右されないネットワークを構築することが出来る。しかし一方で意図しないネットワーク利用や、非効率的なネットワークの構築が起こることもある。しかし現状、P2Pアプリケーションの努力で対策のし難い問題でもある。これはP2Pアプリケーションが実際のネットワーク構成の情報を知る事が難しいことによる。せいぜいエンド間における通信速度やRTTを得るのが限界で、詳細なネットワーク構造を知るには調査用のパケットを飛ばす必要が出る。また、MPLS等の新しい技術や調査に対して応答しないルーターの存在が更に難しいものにしている。

例えば、非効率的なネットワーク利用例としてネットワークの近接性を無視した通信が挙げられる。従来のP2Pアプリケーションの技術では同一AS内など近くに所望のデータがあったとしてもP2Pクライアントではそれを知る術は無い。そのため、わざわざ遠くにあるコンピュータに対してファイル転送を要求してしまう事が発生する。

そこでP4P技術はP2Pクライアントに対して、P2Pクライアント単体では知ることが困難なネットワークの情報を提供する。これにより効率的なネットワーク構築やファイル転送を促し、ネットワークのより効率的、公平に利用できる期待がある。またP4Pにて提供される情報は技術的な情報のみならず、利用ポリシーに関する情報も提供することが出来る。すなわちISPにとって利用を避けて欲しい時間など、P2PがISPと共存していくために必要な情報も提供することが出来る。

こうしたP4P情報を活用するモチベーションはISP側だけのものでは無い。より効率的な転送を実現出来ることはP2Pユーザーにとってもファイルのダウンロードが高速に行えるメリットがある。

近接性を考慮しない通信の例
図2-8. 近接性を考慮しない通信の例

遠方優先アルゴリズム

遠方優先アルゴリズム[6]とは、村松氏が提案したP4P情報を活用することで遠方にあるピアに対して早くファイル転送することを目的としたアルゴリズムである。

P4P情報を活用したファイル転送アルゴリズムとしては素朴な手法(以下、「素朴なP4Pアルゴリズム」)としては、ピア同士の近接性を考慮し、より近くのピア(国内、同一AS内など)に対して優先的にUnchokeする、といったアルゴリズムが考えられる。しかし村松氏の提案するアルゴリズムはこれとは逆の発想からなるものである。

素朴なP4Pアルゴリズムは近接ピアに対するファイル配信は優遇する一方で、遠方ピアに対してはファイル転送を控える。ファイル転送を行えるピアと所望するピアとがネットワーク上に均等に分布しているのであれば問題ないが、偏在する場合には近接となるピア間距離に大きな差が出来てしまう。こうした状況下では、例えば同一AS内を優先するアルゴリズムの場合、同一AS内に所望のファイルを持ったピアが存在しない場合、ダウンロードに非常に時間が掛かることになる。また、そのピア内にファイルを所望するピアが多数ある場合、それぞれが遠方のピアとの通信を要求することになる。これによって無駄な通信が発生する。

すなわちこうした状況を回避する為に考案されたのが「遠方優先アルゴリズム」で、遠方のピア、かつ付近にファイル持ったピアが居ない場合に優先的にファイル配信を行うことでP2Pネットワーク上におけるファイルの均等な分布を促し、さらには無駄な通信を抑えることになる。

遠方優先アルゴリズムによる転送例
図2-9. 遠方優先アルゴリズムによる転送例

第三章 関連研究

2007年、DCIA : P4P Working Group(P4PWG)がXie氏らによる論文「P4P: Explicit Communications for Cooperative Control Between P2P and Network Providers」[4]を公開した。この論文ににおいてISPがP2Pに協力し、情報提供するというP4P技術の提案、及びP4Pを素朴に活用した場合にファイルダウンロード時間を45[%]削減、リンク使用効率を50-70[%]と大幅に改善できることが示されている。なお、特性解析にはPlanetLabと呼ばれる分散アプリケーションの実験用の実環境が用いられている。

続く2008年、早稲田大学の魏氏による論文「P2P トラフィックの効率的制御法」[5]においてP4P情報を活用したアルゴリズムの提案、および特性解析が行われた。彼が提案するアルゴリズムは、P4Pが提供するAS番号の情報を利用することでファイル転送の対象を同一AS内に閉じ込める、という方法である。特性解析には7台のBitTorrentクライアントがインストールされたコンピュータ、Trackerサーバー、及びVyattaがインストールされたルーターマシンからなる実験環境で実際に動作させることで行っている。実験より確かに総トラフィック量が抑えられるていることが示される。

2010年には東京電機大学の村松氏による論文「P4Pを活用してトランジットを軽減するP2Pプロトコル」[6]において同様にP4P活用アルゴリズムとその特性が提示される。彼の論文における提案は「遠方優先アルゴリズム」と呼ばれるアルゴリズムである。その詳細は先の章で示したとおりであるが、BitTorrentのファイル交換ネットワーク上に偏って存在するファイルを出来るだけ遍在させようと促すアルゴリズムである。特性解析にはJavaを用いた自作シミュレータを使って行っている。このシミュレーションにより、特定のネットワークトポロジーにおいてダウンロード完了までにかかる時間、トランジット量、ともに減らすことが出来たと示されている。

さらに2013年には千葉大学の今泉氏らによる論文「P2PダウンロードにおけるISP間トラフィック削減手法の提案」[8]においてP4P活用アルゴリズムとその特性が提示される。この論文で提案されているのはノードの選択(ファイル転送先の選択)に通信速度とISPのホップ数の両方を考慮した指標を用いることで、各ISPリンク間に流れるトラフィックの合計を削減しユーザーのダウンロード時間の増加を抑えるという手法である。これは同一AS内での通信が必ずしも高速では無いことからの提案である。特性解析は自作シミュレータによって行っており、特定の条件下におけるトラフィック量とダウンロード時間の変化の特性が分析された。

このように何人かによってP4Pの活用アルゴリズムの提案がされているが、Xie氏らによる論文を除き、アルゴリズムの特性解析は極めて限られた条件下に留まっており、それぞれが今後の研究課題にしている。

第四章 シミュレーションプログラム

研究目的

本研究はの目的はネットワークシミュレータであるns-3上にBitTorrentプロトコルを実装し特性解析することにある。またBitTorrentプロトコルを支えるファイル転送アルゴリズムとしてP4Pを活用しないもの、及びP4Pを活用したアルゴリズムの両方を実装することで、それぞれの特性比較を行うことを目的とする。なお、本稿で実装しているP4P活用アルゴリズムは村松氏が提案している「遠方優先アルゴリズム」である。

相違点

実装にあたってはBitTorrentの公式仕様書[3]、およびP4P: Explicit Communications for Cooperative Control Between P2P and Network Providers[4]を参考にしている。ただしP4Pについてい次の点には変更を加えている。例えば、本来であればP4P情報はiTrackerと呼ばれるP4P情報配信用のサーバーをAS毎に建てる必要があるが、ns-3ではこれを素直に実装しなくとも、シナリオファイルに記述することでネットワークトポロジーの情報を各クライアントとなるアプリケーションに通知することが出来る。よってiTrackerは実装せず、代わりにTrackerサーバーにおいてP4P情報の提供も行えるように拡張している。

実装したアルゴリズム

実装しているアルゴリズムは以下の表の通りである。

表4-1. 実装したChoke&Unchokeアルゴリズム
アルゴリズム概要
完全ランダムChoke30[s]おきに動作し、現在のUnchoke数が許可可能な上限であるとき、完全ランダムで1つのUnchoke中ピアに対してChokeを行う。
完全ランダムUnchoke接続中のピアの中から完全ランダムで最大4つまでのピアに対してUnchokeを行う。
重み付きランダムUnchoke接続中のピアの中から一定条件を満たすピアに対し選択確率を上げた上で、ランダムで最大4つまでのピアに対してUnchokeを行う。
表4-2. 実装したピース選択アルゴリズム
アルゴリズム概要
完全ランダムピース選択自分の持っていないピースの中から完全ランダムで一つのピースを選択し、転送要求を行う。

アプリケーションの動作

以下に実装したアプリケーションの一連の動作について説明する。

  1. 準備

    BitTorrentの動作に必要なMetainfoファイルはns-3のシナリオファイルにおいて作成する。ここで転送するファイルの長さ、ピースサイズ、及びTrackerサーバーのアドレスなど、シミュレータの利用者が自由に設定することが出来る。また同様にしてネットワークトポロジーの定義やTrackerサーバーアプリケーションのインストール作業もシナリオファイルによって行う。この時点でSeederと呼ばれる完全ファイルを持つピアも定義する。

  2. BitTorrentクライアントの起動

    クライアントが起動するタイミングはns-3のシナリオファイルによって定義される。指定の時間に到達するとクライアントは自動的に立ち上がり、ファイル交換のネットワーク上でピアの識別に用いられる20byte長のIDを生成する。BitTorrent公式の仕様書によるところ、生成アルゴリズムは各実装に任されているために現実のクライアントではネットワーク上で重複が発生することがある、しかし今回シミュレータ上で生成しているものは衝突が起こらない方法によって作成している。

  3. Trackerサーバーとの初回通信

    ピアIDの生成が終わると他のピアからの接続を受け入れられるようSocketをListen状態にする。そしてMetainfoを参照し、Trackerサーバーに対して自身がファイル配信のネットワークに参加したい事を通知すると同時に、既にネットワークに参加している他のピアの情報を受け取る。この間の通信はHTTPプロトコルによって行われ、Trackerサーバーへの登録はGETメソッド、またピアリストからの応答はBencodingと呼ばれる方法でエンコーディングされたデータによって行われる。その後はBitTorrentアプリケーションの終了まで定期的にTrackerサーバーに対してファイルダウンロードの進捗を報告とピアリストの取得を行う。

    GET announce/?info_hash=<>&peer_id=<>&port=<>&upload=<>&downloaded=<>&left=<>&event=<> HTTP/1.1
    改行 (CR + LF)
    改行 (CR + LF)
    

    図4-1. シミュレーションにおけるTrackerサーバーへの登録(クエリー値省略)

    HTTP/1.1 200 OK
    Content-Length: 4891
    改行 (CR + LF)
    改行 (CR + LF)
    <Bencoded Data...>
    <Bencoded Data...>
    

    図4-2. シミュレーションにおけるTrackerサーバーからの応答(一部ヘッダー省略)

  4. ピアとの接続

    Trackerサーバーから得られたピアリストに基づいて接続を行う。どのピアに対して接続を行うのかはBitTorrentクライアントの実装に任されているが、作成したアプリケーションではピアリストの中から完全ランダムで選択している。また、相手ピアとはTCPによって接続を行う。

  5. ハンドシェイク

    相手ピアとのコネクションに成功するとHandshakeメッセージのやりとりを行う。Handshakeメッセージではお互いに転送したいファイルのメタ情報、お互いのピアID、およびオプションの利用不可の状況をやりとりする。Handshakeが完了するとBitfieldを相手に通知する。これは自身の持っているファイルのピースの情報である。

    こちらから接続を行うのと同様に、Trackerサーバーに自身の情報を登録したことによって外部からコネクションを張ってくることもあるが、その場合は送られてきたHandshakeメッセージに対して応答を行う。

  6. Unchoke / Chokeメッセージの送信

    Handshakeが完了したことでファイルの転送や転送許可・不許可といった具体的なやりとりを行うことになる。実装したアプリケーションでは一定の時間間隔でピアとの接続状況を監視して適宜アルゴリズムに応じたUnchoke / Chokeメッセージの送信を行っている。ここで動作するアルゴリズムは先に示したとおりである。

  7. Request / Pieceメッセージの送信

    Unchokeメッセージを受信したピアは、Unchokeメッセージを送信したピアに対してピースファイルの転送を求めるRequestメッセージの送信を行う。Requestメッセージには何番目のピースファイルのどの部分が欲しいのかを記述する必要があり、その内容を決めるアルゴリズムは前述のピース選択アルゴリズムである。

    実装したアプリケーションでは、自身の持っていないピース、かつ、相手は持っているピースの中から完全ランダムで選択することでRequestメッセージを送信している。PieceメッセージとはRequestメッセージの対になるもので、送られてきたRequestメッセージが妥当かつ要求してきたピアに対してUnchokeをしている場合にピースファイルを含むメッセージを応答する。

  8. 終了条件と終了処理

    アプリケーションの終了条件はns-3のシナリオファイルにおいて時間によって定義する。ファイルのダウンロードが完了したピアはSeederとなり、アップロードを続ける。アプリケーションの終了時には接続中のピア全てに対してChokeメッセージをブロードキャストし、かつコネクションの切断処理を行う。

表4-3. ピア間でやりとりされるメッセージ一覧
メッセージ名概要
Handshake Messageピア間での接続を確立するため始めに交換されるメッセージ。BitTorrentプロトコルであることを示すヘッダから始まり、ピアID、所望のファイルのハッシュ値、オプションの利用不可の情報が格納されている。
Keep-Alive Messageコネクションが切断されていないことを確認するため定期的に送信するメッセージ。
Choke Messageデータを配信する意図がない事を伝える。
Unchoke Messageデータ配信する意図がある事を伝える。
Interested Message通知されたBitfield(及びHaveメッセージ)の中に配信して欲しいデータがある事を伝える。
Not-Interested Message通知されたBitfield(及びHaveメッセージ)の中に配信して欲しいデータがない事を伝える。
Have Messageある一つのピースデータを持っていることを伝える。メッセージにはそのピースのインデックス番号が含まれる。
Bitfield Message持っているピースデータの情報をあらわすbitfieldを伝える。通常Handshake後に一度は送信する。
Request MessageUnchokeしてくれたピアに対して任意のピースの配信要求をする。ピースのインデックス番号とオフセット、データ長が含まれる。
Piece Messageファイルの転送を含むメッセージ。Requestをしてくれたピアに対してUnchoking状態であれば送信する。ピースのインデックス番号とオフセットそして実データが含まれる。
Cancel MessageRequestした内容を取り消す時に送信する。

動作サンプル

現時点での動作例を示す。この動作例ではまたUnchoke/Choke/Requestアルゴリズムの実行周期が非常に遅くなっているが、これは短い時間に設定すると大量のログがはき出されてしまうからである。ここでは1[s]おきに実行するようにしている。

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */

// 必要なモジュール(Build-in)のインクルード
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/csma-module.h"
#include "ns3/applications-module.h"

// 必要なモジュール(自作)のインクルード
#include "ns3/BitTorrentTracker.h"
#include "ns3/BitTorrentClient.h"
#include "ns3/MetainfoFile.h"

using namespace ns3;

int 
main (int argc, char *argv[])
{
  // ログの出力設定
  LogComponentEnable ("P2P_SimulationExample", LOG_LEVEL_INFO);
  LogComponentEnable ("BitTorrentClient", LOG_LEVEL_INFO);
  LogComponentEnable ("BitTorrentConnectionManager", LOG_LEVEL_INFO);
  LogComponentEnable ("ClientDatabase", LOG_LEVEL_FUNCTION);
  LogComponentEnable ("ConnectionStrategyBase", LOG_LEVEL_INFO);
  LogComponentEnable ("FullRandomConnectionStrategy", LOG_LEVEL_INFO);
  LogComponentEnable ("ListeningPeerConnection", LOG_LEVEL_INFO);
  LogComponentEnable ("PeerConnection", LOG_LEVEL_FUNCTION);
  LogComponentEnable ("FullRandomRequestStrategy", LOG_LEVEL_FUNCTION);

  // Trackerサーバーとルーターの作成
  NodeContainer trackerBackboneNodes;
  trackerBackboneNodes.Create (2);

  // Trackerサーバー <-> ルーター間の接続設定(Point-to-Point接続: 5Mbps/2ms)
  PointToPointHelper pointToPoint;
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

  // Trackerサーバー <-> ルーター間の接続設定(ネットワークデバイスのインストール)
  NetDeviceContainer trackerBackboneDevices;
  trackerBackboneDevices = pointToPoint.Install (trackerBackboneNodes);

  // ピアの作成
  NodeContainer peerCsmaNodes1;
  NodeContainer peerCsmaNodes2;
  peerCsmaNodes1.Add (trackerBackboneNodes.Get(1));
  peerCsmaNodes2.Add (trackerBackboneNodes.Get(1));


  peerCsmaNodes1.Create(1);
  peerCsmaNodes2.Create(1);

  // ピア <-> ルーター間の接続設定(イーサネットケーブル[CSMA/CD]: 100Mbps/6560ns)
  CsmaHelper csma;
  csma.SetChannelAttribute ("DataRate", StringValue("100Mbps"));
  csma.SetChannelAttribute ("Delay", TimeValue(NanoSeconds(6560)));

  // ピア <-> ルーター間の接続設定(ネットワークデバイスのインストール)
  NetDeviceContainer peerCsmaDevices1;
  NetDeviceContainer peerCsmaDevices2;
  peerCsmaDevices1 = csma.Install (peerCsmaNodes1);
  peerCsmaDevices2 = csma.Install (peerCsmaNodes2);

  // すべてのノードにプロトコルスタックをインストールする
  InternetStackHelper stack;
  stack.Install (trackerBackboneNodes);
  stack.Install (peerCsmaNodes1.Get(1));
  stack.Install (peerCsmaNodes2.Get(1));

  // Trackerサーバー <-> ルーター間のIPアドレス割り当て(10.1.1.0/30)
  Ipv4AddressHelper address;
  address.SetBase ("10.1.1.0", "255.255.255.252");
  Ipv4InterfaceContainer trackerBackboneInterfaces = address.Assign (trackerBackboneDevices);
  
  // ピア <-> ルーター間のIPアドレス割り当て(172.16.1.0/30)
  address.SetBase ("172.16.1.0", "255.255.255.252");
  Ipv4InterfaceContainer peerCsmaInterfaces1 = address.Assign (peerCsmaDevices1);
  
  // ピア <-> ルーター間のIPアドレス割り当て(172.16.2.0/30)
  address.SetBase ("172.16.2.0", "255.255.255.252");
  Ipv4InterfaceContainer peerCsmaInterfaces2 = address.Assign (peerCsmaDevices2);

  // Trackerサーバーのアドレス取得(IPアドレスの自動取得と6969番ポートの指定)
  Address trackerAddress = InetSocketAddress(trackerBackboneInterfaces.GetAddress(0), 6969);

  // Trackerサーバーアプリケーションのインストール
  Ptr<BitTorrentTracker> tracker = Create<BitTorrentTracker>();
  trackerBackboneNodes.Get(0)->AddApplication(tracker);
  tracker->SetStartTime(Seconds(10.));
  tracker->SetStopTime(Seconds(280.));

  // Metainfoファイルの生成(TrackerサーバーのIPv4アドレス/ポート番号/ファイルサイズ10MB/ピースサイズ16KB)
  Ptr<MetainfoFile> info = Create<MetainfoFile>(trackerAddress, 10 * 1024 * 1024, 16 * 1024);

  // BitTorrentクライアントアプリケーションのインストール
  Ptr<BitTorrentClient> client1 = Create<BitTorrentClient>(info, true);
  peerCsmaNodes1.Get(1)->AddApplication(client1);
  client1->SetStartTime(Seconds(20.));
  client1->SetStopTime(Seconds(30.));

  // BitTorrentクライアントアプリケーションのインストール
  Ptr<BitTorrentClient> client2 = Create<BitTorrentClient>(info);
  peerCsmaNodes2.Get(1)->AddApplication(client2);
  client2->SetStartTime(Seconds(10.));
  client2->SetStopTime(Seconds(40.));


  // 全ノードに対してルーティングテーブルを設定する
  Ipv4GlobalRoutingHelper::PopulateRoutingTables();

  // シミュレーションの終了時間の定義
  Simulator::Stop (Seconds (300));
  Simulator::Run ();
  Simulator::Destroy ();

  return 0;
}

図4-3. 簡易な実験用のシナリオファイル

このシナリオで構築しているネットワークは以下の図の通りである。

簡易な実験用のネットワーク
図4-4. 簡易な実験用のネットワーク構成

この実験ではBitTorrentを動作させるために必要最小限の構成で行っている。すなわち、1台のTrackerサーバー、2台のピア(クライアント)、そして、それらを繋ぐルーターからなる。この実験はBitTorrentアプリケーション(Trackerサーバーアプリケーションを含む)の動作検証を目的としており、複数のASを跨いだ通信特性の計測を目的としたものでは無い。

このシナリオファイルで記述している内容は次の図に示す通りである。

  1. ログレベルの設定

    標準エラー出力へと出力するログの内容をログレベルを用いて設定する。

    ※実装したモジュールとシナリオファイルが対象。

  2. Point-to-Point接続

    Trackerサーバーとルーターを作成、その間をPoint-to-Pointで接続する。(シナリオファイル上、両者は同じNodeとして扱われる)

  3. Ethernet接続

    作成したルーターに二台のピアを接続する。この間はEthernetケーブルで接続するのでCSMA/CDが実装されたChannelで接続する。

  4. プロトコルスタックのインストール

    作成したすべてのネットワーク機器にプロトコルスタックをインストールする。

  5. IPv4アドレスの割り振り

    作成したネットワークに対し、IPv4アドレスを割り振る。

  6. Trackerアプリケーションのインストール

    Trackerサーバーからアドレス情報を取得、またPort情報を付加した変数を用意する。そしてTrackerサーバーに専用のアプリケーションをインストールする。

  7. Metainfoファイルの生成

    作成しておいたTrackerサーバーのアドレス情報を基に、Metainfoファイルを作成する。このファイルにおいてファイルサイズなども定義する。

  8. BitTorrentアプリケーションのインストール

    ピアにアプリケーションをインストール。また、Metainfoファイルも読み込ませる。シミュレーション開始時点でのファイルの有無も定義する。

  9. ルーティングテーブルの作成

    作成した全てのネットワーク機器にルーティングテーブルを設定する。

  10. シミュレーションの開始と終了処理

    シミュレーションの終了時間を設定、またシミュレーションに必要な関数を呼び出す。

シミュレータの実行結果は以下のようになった。


[yamato@localhost ns-3.21]$ ./waf --run scratch/SimpleBitTorrent
Waf: Entering directory `/home/yamato/ns-3-allinone/ns-3.21/build'
Waf: Leaving directory `/home/yamato/ns-3-allinone/ns-3.21/build'
'build' finished successfully (5.732s)
Creating Topology
ClientDatabase:ClientDatabase(0x120ca30)
ClientDatabase:ClientDatabase(0x120d1c0)

# BitTorrentアプリケーション起動時間への到達
[NODE_ID:3] 10[s] Start Application
[NODE_ID:2] 20[s] Start Application

# 他のピアへの接続を試みる
[NODE_ID:3] 21[s] Connect to NODE_ID:2
[NODE_ID:2] 21[s] Connect to NODE_ID:3

# 接続に成功する(同時刻に接続を行った為、二重にコネクションが張られてしまう)
[NODE_ID:3] 21.0001[s]  Connection Succeeded.
[NODE_ID:2] 21.0001[s]  Connection Succeeded.
PeerConnection:PeerConnection(0x11d02c0)
FullRandomRequestStrategy:FullRandomRequestStrategy(0x1224910)

# ハンドシェイクを行う(二重にコネクションが張られているため、双方向のハンドシェイクで合計4つの成功メッセージが出ている)
[NODE_ID:3] 21.0001[s] Entrusted a Handshaked Connection [NODE_ID:2] / Connected socket [1/32]
[NODE_ID:3] 21.0001[s] ++++++++++ Handshake with [NODE_ID:2] Succeeded!! (Listening) ++++++++++
PeerConnection:PeerConnection(0x1201b00)
FullRandomRequestStrategy:FullRandomRequestStrategy(0x1224ef0)
[NODE_ID:2] 21.0001[s] Entrusted a Handshaked Connection [NODE_ID:3] / Connected socket [1/32]
[NODE_ID:2] 21.0001[s] ++++++++++ Handshake with [NODE_ID:3] Succeeded!! (Listening) ++++++++++
PeerConnection:PeerConnection(0x11d1c10)
FullRandomRequestStrategy:FullRandomRequestStrategy(0x12254d0)
[NODE_ID:3] 21.0003[s] Entrusted a Handshaked Connection [NODE_ID:2] / Connected socket [2/32]
[NODE_ID:3] 21.0003[s] ++++++++++ Handshake with [NODE_ID:2] Succeeded!! (connection) ++++++++++
PeerConnection:PeerConnection(0x11c1540)
FullRandomRequestStrategy:FullRandomRequestStrategy(0x1225ae0)
[NODE_ID:2] 21.0003[s] Entrusted a Handshaked Connection [NODE_ID:3] / Connected socket [2/32]
[NODE_ID:2] 21.0003[s] ++++++++++ Handshake with [NODE_ID:3] Succeeded!! (connection) ++++++++++

# ファイルのダウンロード進捗をお互いに知らせる(Bitfieldメッセージの送信)
[NODE_ID:2] 21.0004[s] Received a message: 85 byte
PeerConnection:RecvBitfieldMessage(0x11c1540)
[NODE_ID:3] 21.0004[s] Received a message: 85 byte
PeerConnection:RecvBitfieldMessage(0x11d1c10)
[NODE_ID:3] 21.0004[s] Received a message: 85 byte
PeerConnection:RecvBitfieldMessage(0x11d02c0)
[NODE_ID:2] 21.0004[s] Received a message: 85 byte
PeerConnection:RecvBitfieldMessage(0x1201b00)

# アルゴリズムにより相手ピアをUnchoke状態にする
PeerConnection:SendUnchokeMessage(0x11d1c10)
[NODE_ID:3] 22[s] Unchoke [NODE_ID:2] / Unchoking status [1/4]
PeerConnection:SendUnchokeMessage(0x11c1540)
[NODE_ID:2] 22[s] Unchoke [NODE_ID:3] / Unchoking status [1/4]
[NODE_ID:3] 22[s] Received a message: 5 byte
PeerConnection:RecvUnchokeMessage(0x11d02c0)

# Unchokeされたピアが相手にファイル要求する(Pieceメッセージの送信)
FullRandomRequestStrategy:StartRequest(0x1224910)
PeerConnection:SendRequestMessage(0x11d02c0)
[NODE_ID:3] 22[s] Send a request <pieceIndex: 412 begin: 0 requestLength: 16384> message.
[NODE_ID:2] 22[s] Received a message: 5 byte
PeerConnection:RecvUnchokeMessage(0x1201b00)
FullRandomRequestStrategy:StartRequest(0x1224ef0)

# Requestメッセージを受信し、相手の該当のファイルを返信する
[NODE_ID:2] 22.0001[s] Received a message: 17 byte
PeerConnection:RecvRequestMessage(0x11c1540)
[NODE_ID:2] 22.0001[s] Receive a request <pieceIndex: 412 begin: 0 requestLength: 16384> message from [NODE_ID:3]
PeerConnection:GenerateRandomString(0x11c1540)
[NODE_ID:2] 22.0001[s] Return a piece message

# 要求したファイルの返信を確認する
[NODE_ID:3] 22.0029[s] Received a message: 16397 byte
PeerConnection:RecvPieceMessage(0x11d02c0)
[NODE_ID:3] 22.0029[s] Receive piece <pieceIndex: 412 begin: 0 DataLength: 16384> message from [NODE_ID:2]
ClientDatabase:receiveNewPiece(0x120d1c0)

# 新たにピースファイルを取得できたことを接続中のピアにブロードキャストする(Haveメッセージの送信)
PeerConnection:SendHaveMessage(0x11d02c0)
PeerConnection:SendHaveMessage(0x11d1c10)
[NODE_ID:2] 22.0031[s] Received a message: 9 byte
PeerConnection:RecvHaveMessage(0x11c1540)
[NODE_ID:2] 22.0031[s] Received a message: 9 byte
PeerConnection:RecvHaveMessage(0x1201b00)

# アルゴリズムにより新たにUnchokeメッセージを送信する
PeerConnection:SendUnchokeMessage(0x11d02c0)
[NODE_ID:3] 23[s] Unchoke [NODE_ID:2] / Unchoking status [2/4]
PeerConnection:SendUnchokeMessage(0x1201b00)
[NODE_ID:2] 23[s] Unchoke [NODE_ID:3] / Unchoking status [2/4]

# アルゴリズムにより新たにファイル要求を行う
# ここから、リクエストが受理されないために応答が返ってこない
PeerConnection:SendRequestMessage(0x11d02c0)
[NODE_ID:3] 23[s] Send a request <pieceIndex: 103 begin: 0 requestLength: 16384> message.
[NODE_ID:3] 23[s] Received a message: 5 byte
PeerConnection:RecvUnchokeMessage(0x11d1c10)
FullRandomRequestStrategy:StartRequest(0x12254d0)
PeerConnection:SendRequestMessage(0x11d1c10)
[NODE_ID:3] 23[s] Send a request <pieceIndex: 397 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d02c0)
[NODE_ID:3] 24[s] Send a request <pieceIndex: 28 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d1c10)
[NODE_ID:3] 24[s] Send a request <pieceIndex: 565 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d02c0)
[NODE_ID:3] 25[s] Send a request <pieceIndex: 247 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d1c10)
[NODE_ID:3] 25[s] Send a request <pieceIndex: 348 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d02c0)
[NODE_ID:3] 26[s] Send a request <pieceIndex: 341 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d1c10)
[NODE_ID:3] 26[s] Send a request <pieceIndex: 62 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d02c0)
[NODE_ID:3] 27[s] Send a request <pieceIndex: 608 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d1c10)
[NODE_ID:3] 27[s] Send a request <pieceIndex: 225 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d02c0)
[NODE_ID:3] 28[s] Send a request <pieceIndex: 71 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d1c10)
[NODE_ID:3] 28[s] Send a request <pieceIndex: 160 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d02c0)
[NODE_ID:3] 29[s] Send a request <pieceIndex: 623 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d1c10)
[NODE_ID:3] 29[s] Send a request <pieceIndex: 62 begin: 0 requestLength: 16384> message.

# アプリケーションの終了時間への到達
[NODE_ID:2] 30[s] Stop Application

# Unchoke中のピアへのChokeメッセージのマルチキャスト
PeerConnection:SendChokeMessage(0x11c1540)
[NODE_ID:2] 30[s] Choke [NODE_ID:3] / Unchoking status [1/4]
PeerConnection:SendChokeMessage(0x1201b00)
[NODE_ID:2] 30[s] Choke [NODE_ID:3] / Unchoking status [0/4]

FullRandomRequestStrategy:StopRequest(0x1224ef0)
FullRandomRequestStrategy:StopRequest(0x1225ae0)
PeerConnection:SendRequestMessage(0x11d02c0)
[NODE_ID:3] 30[s] Send a request <pieceIndex: 371 begin: 0 requestLength: 16384> message.
PeerConnection:SendRequestMessage(0x11d1c10)
[NODE_ID:3] 30[s] Send a request <pieceIndex: 322 begin: 0 requestLength: 16384> message.
[NODE_ID:3] 30[s] Received a message: 5 byte
PeerConnection:RecvChokeMessage(0x11d02c0)
FullRandomRequestStrategy:StopRequest(0x1224910)
[NODE_ID:3] 30.0001[s] Received a message: 5 byte
PeerConnection:RecvChokeMessage(0x11d1c10)
FullRandomRequestStrategy:StopRequest(0x12254d0)
PeerConnection:HandlePeerClose(0x11d1c10)
FullRandomRequestStrategy:StopRequest(0x12254d0)
PeerConnection:HandlePeerClose(0x11d02c0)
FullRandomRequestStrategy:StopRequest(0x1224910)
[NODE_ID:3] 31[s] Connect to NODE_ID:2
[NODE_ID:3] 32[s] Connect to NODE_ID:2
[NODE_ID:3] 33[s] Connect to NODE_ID:2
[NODE_ID:3] 34[s] Connect to NODE_ID:2
[NODE_ID:3] 35[s] Connect to NODE_ID:2
[NODE_ID:3] 36[s] Connect to NODE_ID:2
[NODE_ID:3] 37[s] Connect to NODE_ID:2
[NODE_ID:3] 38[s] Connect to NODE_ID:2
[NODE_ID:3] 39[s] Connect to NODE_ID:2

# アプリケーションの終了時間への到達
[NODE_ID:3] 40[s] Stop Application
[yamato@localhost ns-3.21]$ 

図4-5. 簡易な実験用シナリオの実行結果

ここでは設定しているシナリオは一台のルーターにTrackerサーバー、2台のピアがスター型で接続されているだけの非常に単純な構成におけるアプリケーションの動作である。また、ここではピア間の通信に関してのみログを出力しているのでTrackerサーバーとのやりとりに関する情報は出力されていない。

上記の通り、現時点ではTrackerサーバーへの接続、他ピアへの接続、ハンドシェイク、Unchokeアルゴリズムによる転送許可、およびRequestメッセージの送信までは成功していることがわかる。しかし一回目のピースデータ配信後、以降Requestメッセージを受け付けていない状況にある。

また同時刻にConnectionを開始してしまうために二重に接続してしまっていることもわかる。そのため以降のピア間のやりとりが二重になってしまっている。

第五章 今後の課題

以下に現時点で把握している問題点を示す。今後の課題はこれらの問題を修正し、BitTorrentアプリケーションとしての動作を完成させること、およびP4Pアルゴリズムの有無でどのように特性が変化するのかを検討することにある。

原因不明の問題

修正中の問題

第六章 まとめ

本研究はネットワークシミュレータであるns-3上においてBitTorrentアプリケーションの実装をすること、またP4Pに関するアルゴリズムの実装を行いどのような特性を示すのか、検討することを目的に行った。ひとまずアプリケーションの実装までは行えたが、現時点ではBitTorrentアプリケーションとしての動作が途中で止まってしまい、特性解析をする段まで辿り着くことが出来ていない。

今後これらのバグを直していき、特性解析まで至ることが課題である。

第七章 参考文献

以下に参考文献と資料を示す。

  1. ns-3, http://www.nsnam.org/
  2. 総務省データ通信課: P2Pネットワーキングの現状と将来, http://www.soumu.go.jp/main_sosiki/joho_tsusin/policyreports/chousa/network_churitsu/pdf/wg2_061129_1_si_1_2.pdf
  3. Bram Cohen,“The BitTorrent Protocol Specification”, http://www.bittorrent.org/beps/bep_0003.html
  4. Haiyong Xie,Arvind Krishnamurthy,Avi Silberschatz, Richard Yang,“P4P: Explicit Communications for Cooperative Control Between P2P and Network Providers”
  5. 魏元, “P2P トラフィックの効率的制御法”, http://www.goto.info.waseda.ac.jp/~wei/file/t5107b024.pdf
  6. 村松謙: P4PによるP2Pの効率化, http://www.net.c.dendai.ac.jp/~muramatsu/p2p_p4p.html
  7. 田柳直人: NS3によるP4Pシステムの伝送特性解析, http://www.net.c.dendai.ac.jp/~tayanagi/
  8. 今泉友輔, 今泉貴史, “P2P ダウンロードにおける ISP 間トラフィック削減手法の提案”, http://www.imit.chiba-u.jp/nipc2013/web_pdf/ipc2013/p df/ipc2013_p011.pdf
  9. Theory.org Wiki: Bittorrent Protocol Specification v1.0, https://wiki.theory.org/BitTorrentSpecification
  10. 江崎浩: P2P教科書(インプレス標準教科書シリーズ), インプレスR&D(2007/12)

第八章 付録

ソースコード

ソースコードのダウンロード

2015/03/18 *.tar.gz

開発したモジュールのソースコードである。以下にクラス毎の概説を示す。

表8-1. BitTorrentアプリケーションとそれに関するクラス
クラス名概要
BitTorrentClientシナリオファイルでインストールに使うクラス。BitTorrentアプリケーションのエントリーポイントになる。
TrackerManagerTrackerサーバーとの通信を担当するクラス。ClientDatabaseを参照しTrackerサーバーへの情報提供を行う。また、返ってきた情報を基にClientDatabaseの更新作業を行う。
ClientDatabaseクライアント上の情報を集約して管理するクラス。
ConnectionManagerピア同士の接続に関する処理利を担当するクラス。主にコネクション数とUnchoke数の監視を行い、具体的な接続作業はコンポジションクラスに任せている。
ListeningPeerConnection外部からの接続受け入れを行う。Handshakeが完了すると、そのコネクションはPeerConnectionクラスに内包されConnectionManagerにて管理される。
PeerConnectionHandshakeが完了しているピアとの通信を行う。
PeerInformation接続前・接続後のピアの情報を格納する。
ConnectionStrategy接続に関するアルゴリズムの内容を定義する。純粋仮想関数を持つConnectionStrategyBaseを継承してアルゴリズムを実装している。
UnchokeStrategyUnchokeに関するアルゴリズムの内容を定義する。純粋仮想関数を持つUnchokeStrategyBaseを継承してアルゴリズムを実装している。
ChokeStrategyChokeに関するアルゴリズムの内容を定義する。純粋仮想関数を持つChokeStrategyBaseを継承してアルゴリズムを実装している。
RequestStrategyピース選択に関するアルゴリズムの内容を定義する。純粋仮想関数を持つRequestStrategyBaseを継承してアルゴリズムを実装している。
BitTorrentProtocolBitTorrentプロトコルを提供する。シングルトン。
表8-2. その他のクラス
クラス名概要
MetainfoFileMetainfoファイル(オブジェクト)の生成や管理に関する機能を提供する。
BitTorrentTrackerTrackerサーバーアプリケーション。クライアントからのリクエストを登録し、また、ピアリストなどをクライアントに対して配信する。
BencodingObjectTrackerサーバーとの通信で用いるBencoding形式のデータを扱う為のクラス。パースしてオブジェクトツリーを生成したり、オブジェクトツリーからシリアライズする機能を提供する。
BitTorrentTools小規模なツールを提供するクラス。URLエンコーディング(パーセントエンコーディング)のエンコーダとデコーダを提供している。