前項 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 を使ってルータと通信を行う事が出来ます。