はじめに
WebサーバーからWebブラウザーなどのクライアントへデータをPush通知する技術として、
SSE(Server-Sent Events) があります。
実際に送信する HTTP Response のデータフォーマットとして、W3C が JavaScript の API を策定しています。HTML5 の API で、EventSource です。
今回は、Server-Sent Events が実際にどのように動くのかを試したい方を対象に、EventSource のフォーマットを使用したWebサーバー側のソースコード、Webブラウザ側のソースコードを紹介します。
参考
- 【まとめ】サーバーからPushする技術の進化(当サイト内)
- W3C - Server-Sent Events(EventSource API)
EventSource のフォーマット
EventSourceフォーマット
event: <イベント名>\n
data: <データ>\n\n
または
data: <データ>\n\n
EventSourceの例
event: ping
data: This is PING.\n\n
Server-Sent Events(SSE):Webサーバー側
- ping イベントを毎秒送信
- ランダムな間隔(秒)でメッセージを送信
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php date_default_timezone_set("America/New_York"); header("Content-Type: text/event-stream\n\n"); header("Cache-Control: no-cache"); $counter = rand(1, 10); while (1) { // "ping" イベントを毎秒送信 echo "event: ping\n"; $curDate = date(DATE_ISO8601); echo 'data: {"time": "' . $curDate . '"}'; echo "\n\n"; // シンプルなメッセージをランダムな間隔で送信 $counter--; if (!$counter) { echo 'data: This is a message at time ' . $curDate . "\n\n"; $counter = rand(1, 10); } // キャッシュされないようにケア ob_end_flush(); flush(); // 1秒待ち sleep(1); } ?> |
Server-Sent Events(SSE):Webブラウザー(クライアント)側
- EventSource に対する addEventListener で ping を受ける
- EventSource の onmessage でランダムな間隔のメッセージを受ける
- HTTPセッションが切断された場合などは onerror で受け取る
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8" /> <META http-equiv="content-style-type" content="text/css" /> <META http-equiv="Pragma" content="no-cache" /> <META http-equiv="Cache-Control" content="no-cache" /> <TITLE>SSE TEST(Client)</TITLE> <SCRIPT type="text/javascript" src="eventsource.js"></SCRIPT> </HEAD> <BODY> <UL id="list"> </UL> </BODY> </HTML> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
var evtSource = new EventSource("server.php"); evtSource.onmessage = function(e) { var newElement = document.createElement("li"); var eventList = document.getElementById('list'); newElement.innerHTML = "message: " + e.data; eventList.appendChild(newElement); } evtSource.addEventListener("ping", function(e) { var newElement = document.createElement("li"); var eventList = document.getElementById("list"); var obj = JSON.parse(e.data); newElement.innerHTML = "ping at " + obj.time; eventList.appendChild(newElement); }, false); evtSource.onerror = function(e) { alert("EventSource failed."); }; |
実行結果
おまけ:CORS(Cross Origin Resource Sharing)
サーバーとクライアントが異なるドメインに所属している(server.php と index.html)場合、
CORS の設定が必要になります。
1 2 3 4 5 6 7 |
date_default_timezone_set("America/New_York"); header("Content-Type: text/event-stream\n\n"); header("Cache-Control: no-cache"); // CROS の設定 header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept'); |