§WebSocket
§Comet ソケットの代わりに WebSocket を使う
Comet ソケットは Web ブラウザへイベントをリアルタイムに送信するためのいわばハックです。また、Comet はサーバからクライアントへの一方向の通信しかサポートしません。サーバへイベントを PUSH 送信する場合は、AJAX リクエストを使います。
現代的な Web ブラウザは WebSocket により双方向のリアルタイム通信をネイティブにサポートしています。
WebSocket は双方向かつ全多重の通信チャンネルを、単一の Transmission Control Protocol (TCP) ソケット上で実現する Web テクノロジです。WebSocket の API は W3C により、一方 WebSocket のプロトコルは IETF により RFC 6455 として、標準化が進められています。
WebSocket は元々、Web ブラウザおよび Web サーバにおいて実装されることを想定して設計されていますが、実際はどんな種類のクライアントやサーバでも利用できます。80 番ポート以外への TCP 接続は家庭内ネットワーク以外では管理者によってブロックされていることがよくありますが、WebSocket を使うとこの制限を迂回することができます。つまり、プロトコルのオーバーヘッドと引き換えにはなりますが、通常の TCP 接続と同じような機能を実現することができ、単一の TCP ポート上で複数の WebSocket サービスを多重化させることもできます。加えて、WebSocket の主な用途は、リアルタイムかつ双方向の通信を要するような Web アプリケーションです。WebSocket が実現するまでは、このような双方向通信を実現しようとすると Comet チャンネルを利用するほかありませんでした。しかしながら、Comet で双方向通信を実現するのはそれほど自明なことではありません。また、TCP ハンドシェイクと HTTP ヘッダによるオーバーヘッドがあるため、メッセージが小さな場合は非効率です。WebSocket プロトコルはこのような問題を、Web のセキュリティ損なわずに解決することを狙っています。
http://en.wikipedia.org/wiki/WebSocket
§WebSocket を使う
これまでは標準的な HTTP リクエストを受け取って標準的な HTTP レスポンスを返すような単純なアクションメソッドを使いました。WebSocket はこれとは全く異なる猛獣なので、このような単純なアクションでは扱えません。
WebSocket を扱うためには、Result
の代わりに WebSocket
を返す必要があります。
public static WebSocket<String> index() {
return new WebSocket<String>() {
// WebSocket のハンドシェイクが完了すると呼ばれます。
public void onReady(WebSocket.In<String> in, WebSocket.Out<String> out) {
// ソケットで受け取ったイベント毎に
in.onMessage(new Callback<String>() {
public void invoke(String event) {
// コンソールにイベントのログを出力する
println(event);
}
});
// ソケットが閉じた時
in.onClose(new Callback0() {
public void invoke() {
println("Disconnected");
}
});
// 単一の `Hello!` というメッセージを送る
out.write("Hello!");
}
}
}
WebSocketは リクエストヘッダ (WebSocket 接続を初期化するための HTTP リクエストに付加されていたもの) を参照することができるため、標準的なヘッダの内容やセッションデータを受け取ることができます。しかし、リクエストボディや HTTP レスポンスへは一切アクセスできません。
WebSocket
の準備が終わると、in
と out
という二つのチャンネルが得られます。
この例では、受け取ったメッセージをコンソールへ出力しつつ、単一の Hello! というメッセージを送信しています。
Tip: WebSocket コントローラは http://websocket.org/echo.html でテストすることができます。テストを行うためには、location として
ws://localhost:9000
を指定してください。
次は、入力データを全て捨てつつ、**Hello!** メッセージを送信した後すぐにソケットを閉じる例を書いてみましょう。
public static WebSocket<String> index() {
return new WebSocket<String>() {
public void onReady(WebSocket.In<String> in, WebSocket.Out<String> out) {
out.write("Hello!");
out.close();
}
};
}
次ページ: テンプレートエンジン