CometBroker を使うクライアントとして、mpchat_webclient/comet.html が提供されている。 これは ajax.html の送受信を分けて行うようにしたものである。
<head>
<script type='text/javascript' src='../mpchat_message/nmljs/json2.js'></script>
<script type='text/javascript' src='../mpchat_message/nmljs/libnine.js'></script>
<script type='text/javascript' src='../mpchat_message/nmljs/message.js'></script>
json2.js は http://www.json.org/json2.jsで配布されているもので、JavaScript 用の JSON ライブラリである。これはまた nineml にも同梱されている。
libnine.js は nineml から生成した JavaScript コードを使う際に必要とされるライブラリである。 nine/tool/nineml に同梱されている。
message.js は、mpchat_message/message.xml から生成された JavaScpirt コードである。
メッセージ送信は sendRequest(channel, qs) 関数に一元化されている。
function sendRequest(channel, qs) {
var host = document.getElementById('input_host').value;
var port = document.getElementById('input_port').value;
var url = 'http://' + host + ':' + port + '/comet/' + channel + '?uniq=' + _uniq;
url += '&' + qs;
++_uniq;
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.charset = 'utf-8';
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script)
}
引数の channel, qs は、リクエストパスの構成に使われる。 特に、channel には "u" か "d" の文字列を与えることで、接続がダウンロードかアップロードかを決めることになる。
HTTPセッションの識別子は、最初の接続の応答で指定される。
セッションが未定のまま Comet の二本の接続をしてしまうと、二本別々のセッションが割り当てられてしまうことになる。
これを避けるため、クライアントの初期化の一環としてダミーの要求を送るようにしている。
function doConnect() {
sendRequest('u', 'jsonp=onHandshake');
}
function onHandshake() {
cometDown();
}
function cometDown() {
sendRequest('d', 'jsonp=onMessage');
}
doConnect() は、GUI から Comet への接続が要求された時に呼ばれる。
doConnect() では sendRequest() でアップロード用チャネル接続を開始する。クエリ文字列には "jsonp=onHandshake" を指定している。 CometMessageHandler の仕様では、アップロードチャネルの応答は常に空の配列が返るようになっている。JSONP の指定は有効なので、onHandshake() 関数がコールバックされることになる。
doConnect で送ったリクエストの応答には、Comet のセッションIDが cookie で指定されている。 よって、onHandshake() 以降の sendRequest() 呼び出しは正しく Comet セッションが指定されるようになる。
onHandshake() は cometDown() 関数を呼ぶ。 cometDown() は sendRequest() に 'd' を渡すことで、ダウンロード用の接続を張る関数である。 同時に jsonp に onMessage を指定し、ダウンロードチャネルから応答が来ると onMessage() 関数を呼びだすようにしている。
function doSay(say) {
var msg = new ChatRequest();
msg.chat.name = name;
msg.chat.chat = say;
msg.from = _lastIndex;
var qs = nine.marshal_querystring(msg);
sendRequest('u', 'jsonp=onUp&' + qs);
}
function onUp(dummy) {
}
ChatRequest オブジェクトを生成し、プロパティをセットアップして sendRequest() へ送っている。sendRequest ではアップロードチャネルを指定し、コールバック関数は onUp である。
アップロードチャネルの応答はメッセージは含まれないので、onUp で何かのデータ操作を行う必要はない。
cometDown() で作られたダウンロードチャネルでは、コールバックに onMessage 関数を指定している。 よって、サーバーからのメッセージは全て onMessage で捉えることができる。
function onMessage(ary) {
var msg;
for (var i=0; i<ary.length; ++i) {
msg = nine.unmarshal_json_object(ary[i]);
if (msg.messageId == LogNotify.MESSAGE_ID) {
addLog(msg);
}
}
cometDown();
}
前半の for ループでは、ajax.html と同様に配列要素のオブジェクトを nine メッセージへ変換して、チャットログへ追記している。
最後に cometDown() を呼び、新たなダウンロードチャネルの構築を行う。