最近、サーバサイドでの対応が必要な HTML5 関連技術について調べていました。しばやんです。
WebSocket は WCF WebSockets 使ったら楽勝!でしたが、HTML5 には Server-Sent Events という Comet を簡単に使えるようにした機能が用意されています。これは HTTP 上で動作するので、わざわざ WCF 周りを使うは必要なくて MVC だけで完結することが出来ます。
とりあえず Server-Sent Events の最新仕様です。
http://www.w3.org/TR/eventsource/
大雑把に説明すると以下のようなデータをクライアント側に返すだけです。ただし、コネクションは張りっぱなしになるので、サーバリソース周りは Comet の時と同様に気を付けないといけません。
id: 1 data: hauhau retry: 1000
id はこのイベントの ID、data は送信するデータ、retry は再接続する際の待ち時間 (ms) になっています。ちなみに最後に送信された id の値は、クライアントからのリクエストに Last-Event-ID というヘッダで付加されてくるので、どのデータまで送信したか分かるわけですね。
最後に忘れやすい点として、このデータを送信する際には Content-Type を text/event-stream にする必要があることです。適切に設定されていない場合には、データは送信されているのにイベントが呼ばれないことになります。
今回、Server-Sent Events のサーバ側を MVC 4 の非同期コントローラを利用して実装しました。コードは以下の通りです。
public async Task<ActionResult> Event() { // 今回は非同期で 5 秒待つ await Task.Delay(5000); // クライアントに送信するデータを作成 var data = "id: 1\n"; data += "data: hauhau\n"; data += "retry: 1000"; // text/event-stream として返す return Content(data, "text/event-stream"); }
本来ならば Task.Delay の部分をイベント完了待ちとかにする必要がありますが、プロトコルがシンプルなのでデータを返す部分は MVC の Content メソッドで問題ありません。
そしてクライアント側は単純にメッセージを受け取って、リスト表示するだけとなっています。
<script type="text/javascript"> $(function () { var source = new EventSource("/Home/Event"); source.onmessage = function (e) { $("<li />").text(e.data).appendTo("#list"); }; }); </script> <ul id="list"></ul>
Server-Sent Events をクライアント側から使うには EventSource オブジェクトを使います。初期化時に URL を指定してイベントを登録すると、後はサーバ側の応答待ちとなり、応答がある度に onmessage に登録した関数が呼び出されます。
実際に動かすと以下のようになります。ブラウザの対応状況としては IE 以外だと大体使えるようです。
レスポンスが返ってくるまでに 5 秒かかっていますね。コネクションが自動的に張り直されるので、継続的にイベントを受け取ることが出来ています。
別に ASP.NET だから HTML5 関連技術が使えないということはないので、こういった記事が増えるのを期待したいですね。