Server-Sent Eventsについて
Server Sent Eventsを使ってサーバ側からクライアント側への通信をする方法があります。
通信時にはEventSorceオブジェクトのインスタンスを生成し、そのコンストラクタに
サーバ側のURLを渡します。
サーバ側では、任意の処理を行い、クライアント側に処理結果を返し、
クライアント側では返されたオブジェクトのmessageイベントを処理します。
messageイベントには、dataプロパティがあり、サーバ側から返された文字列が格納されています。
また、typeプロパティにはデフォルトでmessageが格納されています。
実装の仕方によっては、サーバ側から返されたイベントソースが複数あり、その全てのイベントを受取る方法として
typeプロパティを使うこともあります。
Server-Sent Eventsのプロトコルについて
Server-Sent Eventsのプロトコルについては、HTTP/1.1で動作します。
これは1回のリクエスト&レスポンス(通信)で、1つの送信&受信を行う。と定義されています。
(ちなみにHTTP/2では、一回の通信で、複数の送信&受信をまとめて通信することができます)
EventSorceオブジェクトのインスタンスを生成したときに、クライアントサーバに接続されます。
サーバ側はこの接続をオープン状態のまま維持します。
サーバ側の処理について
サーバ側の処理は、Server-Sent Eventsで接続されているオープン状態の接続に対してテキストを送信します。
その際の「Content-Type」は以下のようにします。
Content-Type: text/event-stream
また、サーバ側では、「データ名:値」のセットになるように文字列を出力します。
データ名は任意で大丈夫ですが、クライアント側と合わせる必要があります。
例えば次のようになります。
data: sample123
テキストが送信されると、クライアント側でイベントが発生して、その内容を受信および処理ができます。
ここまでをふまえて、簡単なHTMLを用意しました。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>テストHTML</title> </head> <body> <div id="sse"></div> <script type="text/javascript"> // データ確認用のdivタグ let dom_sse = document.getElementById("sse"); // EventSorceオブジェクトのインスタンスを生成 let testsse = new EventSource("server_sent_event.php"); // サーバ側から応答があった時の処理 testsse.onmessage = function(event) { // サーバ側から送られた内容を受信し、JSONパースをする let recieve_data = JSON.parse(event.data); // ログ出力で内容確認 console.log("recieve_data.data1 -> " + recieve_data.data1); console.log("recieve_data.data2 -> " + recieve_data.data2); // サーバ側から受信したテキストをDOMへ描画(data1のみ) dom_sse.innerHTML += recieve_data.data1 + "<br />"; } </script> </body> </html>
サーバ側のphpは次のように書きました。
「Content-Type」を「text/event-stream」にしている点と、
出力するデータの名称を「data:」として、値をjson形式にしている点、
それと、「ob_end_flush();」と「flush();」で、出力方法を制御している点に注意が必要です。
<?php // server_sent_eventデモ header("Cache-Control: no-store"); header("Content-Type: text/event-stream"); $sample_data = date("Y/m/d H:i:s"); // 返却用のサンプルデータを用意 $result_arr = array( "data1" => $sample_data, "data2" => "test1234" ); echo "data: " . json_encode($result_arr) . "\n\n"; ob_end_flush(); flush(); ?>
画面にアクセスして動きをみると、画面上に時刻が表示されることがわかります。
(日時はダミーです)
onmessageのテスト 2022/09/07 21:22:21 2022/09/07 21:22:24 2022/09/07 21:22:27 2022/09/07 21:22:30
また、通信が行われるタイミングは約3秒ごとに発生していますが、
これはどこで制御されているのかは不明なので、改めてわかった時点で内容を更新しようと思います。