サーバー送信イベントは HTML 5 仕様のコンポーネントであり、サーバーからブラウザーにリアルタイムでデータをプッシュするために使用できます。同様の COMET および WebSocket テクノロジと比較して、サーバー プッシュ イベントは使用が簡単で、サーバー側で必要な変更が少なくなります。一部の種類のアプリケーションでは、サーバー プッシュ イベントが最適なオプションです。
WebSocket
HTML 5 サーバー プッシュ イベントを導入する前に、まず、上記のサーバー側データ プッシュ テクノロジのいくつかを導入します。 1つ目はWebSocketです。 WebSocket 仕様は HTML 5 の重要な部分であり、多くの主流ブラウザでサポートされています。また、WebSocket に基づいて開発されたアプリケーションも数多くあります。名前が示すように、WebSocket は TCP プロトコルに基づいたソケット接続を使用します。 WebSocket を使用すると、サーバーとブラウザーの間にソケット接続が実際に確立され、双方向のデータ送信が可能になります。 WebSocket は非常に強力かつ柔軟に使用できるため、さまざまなシナリオに適用できます。ただし、WebSocket テクノロジは、一般的な Web アプリケーションとは異なるサーバー側およびブラウザ側の実装を含め、比較的複雑でもあります。
ポーリング
WebSocket に加えて、他の実装方法は HTTP プロトコルに基づいて、リアルタイムのプッシュ効果を実現します。 1 つ目の方法は単純なポーリングです。つまり、ブラウザは定期的にサーバーにリクエストを送信して、データの更新があるかどうかを確認します。このアプローチは比較的単純であり、問題をある程度解決できます。ただし、ポーリング間隔は慎重に検討する必要があります。ポーリング間隔が長すぎると、ユーザーは更新データを時間内に受信できなくなります。ポーリング間隔が短すぎると、クエリ要求が多すぎてサーバーの負荷が増加します。
欠点:
1: ポーリングはクライアントによって開始されるため、特定の情報がすべてのクライアントにプッシュされたかどうかを判断するのは難しいため、サーバーはプッシュしたいコンテンツの有効期限が切れているかどうかを判断できません。サーバーは大量のデータをキャッシュする必要があります。データがデータベースに保存されている場合、リクエストごとにデータベースにクエリを実行する必要があり、これはデータベース設計とシステム設計の両方にとって大きな課題です。
2: リクエストの頻度が高すぎます。各リクエスト パケットには同じデータが含まれています。これは PC にとっては大したことではないかもしれませんが、モバイル クライアントにとっては最適な解決策ではありません。特に権限の判断に関しては、サーバーのロジックと効率もユーザーエクスペリエンスを低下させます。
COMET
COMET テクノロジーは、単純なポーリングの欠点を改善し、ロング ポーリングを使用します。ロングポーリング方式では、サーバーは応答が完了した直後に接続を閉じるのではなく、各リクエスト中に一定期間接続を開いたままにします。この利点は、接続が開いている間、サーバーによって生成されたデータ更新をタイムリーにブラウザに返すことができることです。以前の長い接続が閉じられると、ブラウザはすぐに新しい長い接続を開いてリクエストを続行します。ただし、COMET テクノロジーの実装には、サーバー側とブラウザー側の両方でサードパーティ ライブラリのサポートが必要です。
現在、ほとんどの Web アプリには次のような Ajax が搭載されています。
上記の 4 つの異なるテクノロジーの包括的な比較。単純なポーリングは、それ自体に欠陥があるため推奨されません。 COMET テクノロジーは HTML 5 標準の一部ではないため、標準準拠の観点からその使用は推奨されません。 WebSocket 仕様とサーバー プッシュ テクノロジは両方とも HTML 5 標準のコンポーネントであり、主流のブラウザでネイティブ サポートを提供することが推奨されています。ただし、WebSocket 仕様はより複雑で、複雑な双方向データ通信を必要とするシナリオに適しています。単純なサーバー データ プッシュ シナリオの場合は、サーバー プッシュ イベントを使用するだけで十分です。
データベースのプッシュは次のようになります。データソースに新しいデータがあると、クライアントのリクエストを待たずにすぐにクライアントに送信されます。この新しいデータは、最新のニュース、最新の株価、友人からのチャット メッセージ、天気予報などです。
データのプルとプッシュの機能は同じで、ユーザーは新しいデータを取得します。ただし、データプッシュにはいくつかの利点があります。 Comet、Ajax プッシュ、リバース Ajax、HTTP ストリーミング、WebSocket、SSE は異なるテクノロジであることを聞いたことがあるかもしれません。おそらく最大の利点は低遅延です。 SSE は、ユーザーによるアクションを必要とせずにデータを更新するために Web アプリケーションによって使用されます。
WebSocket はサーバーを実装するためのより複雑なテクノロジですが、サーバーはデータをクライアントにプッシュでき、クライアントもデータをサーバーにプッシュできます。 SSE は HTTP/HTTPS プロトコルで動作し、プロキシ サーバーと認証テクノロジをサポートします。 SSE はテキスト プロトコルであり、簡単にデバッグできます。主にバイナリ データをサーバーからクライアントに送信する必要がある場合は、WebSocket の方が適しています。
幸いなことに、HTML5 は私たちに方法を提供します。Server-Sent Events には、私のニーズを満たすための新しい HTML 要素 EventSource と新しい MIME タイプ text/event-stream が含まれています。
サーバー送信イベント API は、EventSource インターフェイスです。新しい EventSource オブジェクトを作成するときに、イベントを受信するための URI を指定できます。例:
var evtSource = new EventSource("ssedemo.php");
<!DOCTYPE html><html><head> <title>sever Sent Event实例1</title></head><body> <h2>sever Sent Event实例1</h2> <p id="result"></p> <script type="text/javascript"> var result = document.getElementById('result'); if (typeof (EventSource) !== 'undefined') { //创建事件源 var source = new EventSource('test.php'); //监听事件源发送过来的数据 source.onmessage = function(event){ result.innerHTML +=event.data +'<br>'; } }else{ result.innerHTML += "您的浏览器不支持server sent Event"; } </script></body></html>
<?php //指定发送事件流的MIME为text/event-stream header('Content-Type:text/event-stream'); //不缓存服务端发送的数据 header('Cache-Control:no-cache'); //指定服务器发送的事件名 echo "event:test\n\n"; // 定义服务器向客户端发送的数据 echo "data:服务器当前时间为:".date('Y-m-d H:i:s')."\n\n"; //向客户端发送数据流 flush(); ?>
ヘッダー「Content-Type」を「text/」に設定します。イベントストリーム"
ページがキャッシュされないことを規定します
出力送信日 (常に "data: " で始まります)
出力データを Web ページに更新します
プッシュされた情報の 1 つが終了フラグとして「nn」を使用していることに注意してください。テスト後、「nn」が終了フラグとして使用されていない場合、クライアントはプッシュされた値を受け取ることができません。また、特別なステートメントを作成する必要があります。プッシュされる情報の形式は "data:contentnn" でなければなりません。それ以外の場合は。 。 。
フィールド
event Event type。このフィールドが指定されている場合、クライアントがメッセージを受信すると、現在の EventSource オブジェクトでイベントがトリガーされます。イベント タイプは、フィールドのフィールド値です。addEventListener() メソッドを使用して、現在のイベントをリッスンできます。 EventSource オブジェクト。メッセージにイベント フィールドがない場合、メッセージのデータ フィールドのイベント処理関数がトリガーされます。複数のデータ フィールドが含まれる場合、クライアントはフィールド値として改行文字を使用して文字列に連結されます。
id イベント ID は、現在の EventSource の内部プロパティ「最後のイベント ID」のプロパティ値になります。 object.
retry 再接続時間 (ミリ秒単位) を指定する整数値。
上記で指定したフィールド名を除き、他のすべてのフィールド名は無視されます。 Chrome は 3 秒ごとにクライアントにプッシュされますが、FF は 5 秒ごとにプッシュされます。
注: テキスト行にコロンが含まれていない場合、テキスト行全体がフィールド名に解析され、そのフィールド値は空になります。
EventSource オブジェクトによって提供される標準イベント
説明
イベント処理メソッドopen | サーバーとの接続が正常に確立されたときに生成されます | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
メッセージ | サーバーによって送信されたイベント受信 | メッセージ | ||||||||
エラー | エラーが発生したときに生成 | onerror | ||||||||
<!DOCTYPE html><html><head> <title>sever Sent Event实例1</title></head><body> <h2>sever Sent Event实例1</h2> <button onclick="closeCnt()">断开连接</button> <p id="result"></p> <script type="text/javascript"> var result = document.getElementById('result'); if (typeof (EventSource) !== 'undefined') { //创建事件源 var source = new EventSource('test.php'); //监听事件源发送过来的数据 source.onmessage = function(event){ result.innerHTML +=event.data +'<br>'; } source.onopen = connectionOpen; source.onclose = connectionClose; function connectionOpen(){ if (source.readyState == 0) { result.innerHTML +='未建立连接<br>'; } if (source.readyState == 1) { result.innerHTML +='连接成功<br>'; } } function connectionClose(){ result.innerHTML += "关闭连接,readyState属性值为:" + source.readyState + '<br>'; } function closeCnt(){ source.close(); result.innerHTML += "断开连接,readyState属性值为:" + source.readyState + '<br>'; } }else{ result.innerHTML += "您的浏览器不支持server sent Event"; } </script></body></html> ログイン後にコピー ログイン後にコピー 在指定 URL 创建出 EventSource 对象之后,可以通过 onmessage 和 addEventListener 方法来添加事件处理方法。当服务器端有新的事件产生,相应的事件处理方法会被调用。EventSource 对象的 onmessage 属性的作用类似于 addEventListener( ‘ message ’ ),不过 onmessage 属性只支持一个事件处理方法。 <!DOCTYPE html><html><head> <title>sever Sent Event实例1</title></head><body> <h2>sever Sent Event实例1</h2> <p id="result"></p> <script type="text/javascript"> var result = document.getElementById('result'); if (typeof (EventSource) !== 'undefined') { //创建事件源 var source = new EventSource('test.php'); //自定义事件源发送过来的数据,事件名和php中事件名对应 source.addEventListener('myevent', 'updateRequests', false); // source.onmessage = function() { // result.innerHTML = event.data + '<br>'; // } function updateRequests(event){ result.innerHTML = event.data + '<br>'; } }else{ result.innerHTML += "您的浏览器不支持server sent Event"; } </script></body></html> ログイン後にコピー ログイン後にコピー <?php //指定发送事件流的MIME为text/event-stream header('Content-Type:text/event-stream'); //不缓存服务端发送的数据 header('Cache-Control:no-cache'); //指定服务器发送的事件名 echo "event:myevent\n\n"; // 定义服务器向客户端发送的数据 echo "data:服务器当前时间为:".date('Y-m-d H:i:s')."\n\n"; //向客户端发送数据流 flush(); ?> ログイン後にコピー ログイン後にコピー 前端是HTML5,后端可以是PHP, JSP, Node.js, Asp.net等应用。 服务器推送事件(Server-sent Events)是 HTML 5 规范中的一个组成部分,可以用来从服务端实时推送数据到浏览器端。相对于与之类似的 COMET 和 WebSocket 技术来说,服务器推送事件的使用更简单,对服务器端的改动也比较小。对于某些类型的应用来说,服务器推送事件是最佳的选择。
1:轮询是由客户端发起的,那么在服务端就不能判别我要推送的内容是否已经过期,因为我很难判断某个信息是否已经推送给全部的客户端,那么服务端就需要缓存大量的数据。如果数据保存在数据库,那么还要每次请求都需要查询数据库,这对数据库和系统设计都是一个很大的挑战。 2:请求的频率太高,每次的请求包中含有同样的数据,这对pc来说也许算不得什么,但是对于移动客户端来讲,这应该不是最佳的方案。尤其是遇到还要做权限判断的时候,那么服务端的逻辑和效率也会造成用户体验的降低。
现在Web App中,大都有Ajax,是这样子:
基于数据推送是这样的,当数据源有新数据,它马上发送到客户端,不需要等待客户端请求。这些新数据可能是最新闻,最新股票行情,来自朋友的聊天信息,天气预报等。 数据拉与推的功能是一样的,用户拿到新数据。但数据推送有一些优势。 你可能听说过Comet, Ajax推送, 反向Ajax, HTTP流,WebSockets与SSE是不同的技术。可能最大的优势是低延迟。SSE用于web应用程序刷新数据,不需要用户做任何动作。 WebSocket はサーバーを実装するためのより複雑なテクノロジですが、サーバーはデータをクライアントにプッシュでき、クライアントもデータをサーバーにプッシュできます。 SSE は HTTP/HTTPS プロトコルで動作し、プロキシ サーバーと認証テクノロジをサポートします。 SSE はテキスト プロトコルであり、簡単にデバッグできます。主にバイナリ データをサーバーからクライアントに送信する必要がある場合は、WebSocket の方が適しています。 幸いなことに、HTML5 は私たちに方法を提供します。Server-Sent Events には、私のニーズを満たすための新しい HTML 要素 EventSource と新しい MIME タイプ text/event-stream が含まれています。 サーバー送信イベント API は、EventSource インターフェイスです。新しい EventSource オブジェクトを作成するときに、イベントを受信するための URI を指定できます。例: var evtSource = new EventSource("ssedemo.php"); ログイン後にコピー ログイン後にコピー <!DOCTYPE html><html><head> <title>sever Sent Event实例1</title></head><body> <h2>sever Sent Event实例1</h2> <p id="result"></p> <script type="text/javascript"> var result = document.getElementById('result'); if (typeof (EventSource) !== 'undefined') { //创建事件源 var source = new EventSource('test.php'); //监听事件源发送过来的数据 source.onmessage = function(event){ result.innerHTML +=event.data +'<br>'; } }else{ result.innerHTML += "您的浏览器不支持server sent Event"; } </script></body></html> ログイン後にコピー ログイン後にコピー <?php //指定发送事件流的MIME为text/event-stream header('Content-Type:text/event-stream'); //不缓存服务端发送的数据 header('Cache-Control:no-cache'); //指定服务器发送的事件名 echo "event:test\n\n"; // 定义服务器向客户端发送的数据 echo "data:服务器当前时间为:".date('Y-m-d H:i:s')."\n\n"; //向客户端发送数据流 flush(); ?> ログイン後にコピー ログイン後にコピー
プッシュされた情報の 1 つが終了フラグとして「nn」を使用していることに注意してください。テスト後、「nn」が終了フラグとして使用されていない場合、クライアントはプッシュされた値を受け取ることができません。また、特別なステートメントを作成する必要があります。プッシュされる情報の形式は "data:contentnn" でなければなりません。それ以外の場合は。 。 。 フィールド
説明 イベント処理メソッド
|