言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

Croquet2D の低レベル通信詳細

前項 http://d.hatena.ne.jp/propella/20060701/p1 でちょっとだけ書いた Croquet2D の低レベル通信について書きます。Croquet 2D では、単純な TCP のクライアントサーバモデル一本で通信を行います。従って、通信に必要な情報はホストアドレスとポート番号、ユーザ名とパスワードです。

Croquet2D で一番重要な機能は、二つのアイランドの内容を同期させるという事ですが、アイランド間を飛び交うイベントと、実際に TCP/IP でやり取りされるデータの間には低レベル通信の層があります。これを理解する事によって、より細かく Croquet2D の制御を行う事が出来ます。Croquet2D の上位層は、正直都合の良い前提を置きすぎな感がありますが、この下位層は割りとまともなので、応用もしやすいと思います。

要素

  • OID : オブジェクトを参照する ID。16 バイトの乱数が振られる。
  • future メッセージ(上位層) TDataMessage にカプセル化
    • レシーバは OID で参照。アイランド内のオブジェクト。
    • 引数はシリアライズしたオブジェクト。基本的に参照ではなくコピー。
  • datagram(下位層) TDatagram にカプセル化
    • facet と data の組。facet は OID。data は任意のバイト列。
    • facet は処理の種類を表す。send:from: を実行したり send:from: したりする。
    • 「facet を送る」とは、「facet の OID を送る」事を言います。
    • どんな facet が有効かは通信の最初に決定します。
    • facet の OID は乱数なので、認証無しに特定の意味を持つ facet を送る事は出来ません。
  • facets
    • facet の OID から実際の処理を探すための辞書
    • キーは OID 値は MessageSend

通信に使われるクラス

  • クライアント側
    • TSimpleController : イベントを受け取り、アイランドを操作する。
    • TRemoteControllerConnection : サーバと実際に通信を行う。
  • サーバ側
    • TExampleDispather : 大本のサーバ。リッスンしている。
    • TSimpleRounter : 一つの共有を表す。
    • TMessageRouterClient : クライアントと実際に通信を行う。

下位プロトコル

TMessageRelay >> sendDatagram: によると、

  • 4バイト: data 長
  • 4バイト: チェックサム
  • 16バイト: facet
  • のこり: data
  • 一度に送る長さが 512 を超える場合はちょっと変わるかも知れません。

通信の手順

簡単に言うと、クライアントはルータ(サーバ)から与えられた facet を通じてのみ通信を行う事が出来るという風になっています。また、独自の facet を定義するには TMessageRouter >> initializeFacets を定義すると良いみたいです。

  • ルータが起動しています。
  • ルータにユーザ名とパスワードが追加されると、そのハッシュ値を元にログイン用 facet が生成されます。ログイン用 facet の内容は login:from: です。
  • クライアントはユーザとパスワードで接続します。その後ログイン用 facet を送信します。 ログイン用 facet の data には listFacet が含まれています。
  • ルータは login:from: を実行し、listFacet を送信します。listFacet の data には、通信に必要な様々な facet が含まれています。どんな facet があるかは TMessageRouter >> initializeFacets を参照してください。
  • クライアントは通信に必要な facet を得る事が出来たので、以降与えられた facet を使ってルータと通信を行う事が出来ます。