Cometメッセージハンドラ

CometMessageHandler

CometMessageHandler は、Cometサーバーで nineメッセージ通信を行うためのフレームワーククラスである。

CometMessageHandler の定義

CometMessageHandler 定義から、一般的に使う部分を抜き出すと次のようになっている:
class CometMessageHandler: public HttpHandler
{
   public:
      bool initialize(const CometMessageHandlerConfig* pCfg);

      virtual void turn(); //!< HTTPセッションの時間切れ判定を行う

      virtual bool handleMessage(Message* pMsg);
      bool post(int sid, const Message*, const SendContext* = NULL);
      bool queue(int sid, Message*, const SendContext* = NULL);
      bool flow(int sid);
      void closeLater(int sid);

      virtual void onSessionOpen(int sid);
      virtual void onSessionClose(int sid);
  ...
};
HttpMessageHandler と同様の関数が提供されている。

CometMessageHandler は HttpHandler を継承している。利用するには、HttpHandler と同様に HttpServer の authorizeHttp() 関数の戻り値で渡せばよい。

HttpHandler は、onHttpRequest() などの生の HTTP を扱うためのハンドラ関数を実装する必要があった。HttpMessageHandler ではこれらのハンドラ関数の実装をしているので、アプリケーション側でさらにオーバーライドする必要はない。

サーバーの振る舞い

CometMessageHandler では、アップロード用とダウンロード用の二本の HTTPセッションを用いる。 二本のセッションをまとめて、一つの仮想的な接続として振る舞う。

クライアントは HttpMessageHandler に対すると同様に HTTP セッションを指定する。 ダウンロード用の接続は常時張っておき、アップロード用接続は送信するメッセージがある時に張る。

Comet 接続のタイムアウトは、ダウンロード用接続のタイムアウトを用いる。

リクエストパス

HTTPリクエストパスが "/u" で終わる場合はアップロード用のチャネル、"/d" で終わる場合はダウンロード用チャネルとみなす。

どちらの接続でも、同一のセッションIDを用いる。

初期化

CometMessageHandler は initialzie 関数を実装している。オブジェクトの生成後にこの関数を呼んで、適切に設定を行う必要がある。

パラメータに与える CometMessageHandlerConfig 構造体は次のように定義されている:
struct CometMessageHandlerConfig
{
      int nSessions; //!< セッションの数
      int sessionTimeoutSec; //!< 次のHTTPリクエストが来るまでセッションを維持する時間[秒]

      // sessionCookie か sessionQueryString のどちらかの指定は必須
      std::string sessionCookie; //!< セッション情報を保持する cookie 名を指定。
      std::string sessionCookiePath; //!< セッション用 cookie のパス
      std::string sessionCookieDomain; //!< セッション用 cookie のドメイン
      std::string sessionQueryString; //!< セッション情報を保持する querystring の key を指定。

      std::string jsonp; //!< 応答を JSONP 形式で行う。JSONP関数名を保持する key を指定。

      // enableQueryStringMarshal か enablePostMarshal のどちらかの指定は必須
      bool enableQueryStringMarshal; //!< QueryString へのメッセージ直列化を処理する
      bool enablePostMarshal; //!< POST Body へのメッセージ直列化を処理する
項目は HttpMessageHandlerConfig と同じである。

turn

HttpMessageHandler と同様に、CometMessageHandler では定期的に turn() を呼ぶ必要がある。

turn() では、セッションの時間切れ判定を行うほか、キューイングされたメッセージの送信も行う。

さらに、何らかのメッセージが送信されていた場合、ダウンロードポートを閉じる処理も行う。

セッション接続関数

セッションの新規確立時には onSessionOpen() が、セッションの終了 OnSessionClose() が呼ばれる。

セッションはタイムアウトで切断されるが、明示的に閉じたい場合には closeLater() を呼ぶ。

メッセージ関数

handleMessage(), post(), queue(), flow() といった一連のメッセージ関数を定義している。 これらの使い方は基本的に MessageServer と同じであるが、Comet 実装に起因する制約がある。
  • post() は、ダウンロードチャネルが接続されていないと失敗する
  • queue() はいつでもできる。
  • キューイングメッセージは、flow() を呼んだ後の turn() で書き出される。ただし flow() はダウンロードチャネルが接続している時でないと動作しない。

handleMessage() で受け取ったメッセージオブジェクトの Message::getCommunicatorId() を呼び出して得られる値は、コミュニケータIDではなくセッションIDになっている。

ダウンロード接続の動作

CometMessageHandler では、ダウンロード接続はすぐには切断しない。 具体的には、onHttpRequest() 関数で endResponse() を呼ばない。

切断は、post() または flow() によりメッセージを送信した後の turn() で行われる。

次のダウンロード接続が来るまでの間は、ダウンロード接続は存在しない。 この時に post() を行うと失敗となる。

アップロロード接続の動作

CometMessageHandler では、アップロード接続はメッセージを受け取るだけである。

受け取ったメッセージは handleMessage() 関数に渡される。

HTTP応答で送るメッセージは無いのだが、HttpMessageHandler の流儀に従って JSON 配列を含める。 もちろん配列は空である。 もし HTTP要求に JSONP が指定されていた場合は、JSONP 形式で返す。