HTML5 サーバープッシュサーバー送信イベント

黄舟
リリース: 2017-02-16 14:28:07
オリジナル
2272 人が閲覧しました


サーバー送信イベントは HTML 5 仕様のコンポーネントであり、サーバーからブラウザーにリアルタイムでデータをプッシュするために使用できます。同様の COMET および WebSocket テクノロジと比較して、サーバー プッシュ イベントは使用が簡単で、サーバー側で必要な変更が少なくなります。一部の種類のアプリケーションでは、サーバー プッシュ イベントが最適なオプションです。

  • WebSocket
    HTML 5 サーバー プッシュ イベントを導入する前に、まず、上記のサーバー側データ プッシュ テクノロジのいくつかを導入します。 1つ目はWebSocketです。 WebSocket 仕様は HTML 5 の重要な部分であり、多くの主流ブラウザでサポートされています。また、WebSocket に基づいて開発されたアプリケーションも数多くあります。名前が示すように、WebSocket は TCP プロトコルに基づいたソケット接続を使用します。 WebSocket を使用すると、サーバーとブラウザーの間にソケット接続が実際に確立され、双方向のデータ送信が可能になります。 WebSocket は非常に強力かつ柔軟に使用できるため、さまざまなシナリオに適用できます。ただし、WebSocket テクノロジは、一般的な Web アプリケーションとは異なるサーバー側およびブラウザ側の実装を含め、比較的複雑でもあります。

  • ポーリング
    WebSocket に加えて、他の実装方法は HTTP プロトコルに基づいて、リアルタイムのプッシュ効果を実現します。 1 つ目の方法は単純なポーリングです。つまり、ブラウザは定期的にサーバーにリクエストを送信して、データの更新があるかどうかを確認します。このアプローチは比較的単純であり、問​​題をある程度解決できます。ただし、ポーリング間隔は慎重に検討する必要があります。ポーリング間隔が長すぎると、ユーザーは更新データを時間内に受信できなくなります。ポーリング間隔が短すぎると、クエリ要求が多すぎてサーバーの負荷が増加します。

HTML5 サーバープッシュサーバー送信イベント
欠点:

1: ポーリングはクライアントによって開始されるため、特定の情報がすべてのクライアントにプッシュされたかどうかを判断するのは難しいため、サーバーはプッシュしたいコンテンツの有効期限が切れているかどうかを判断できません。サーバーは大量のデータをキャッシュする必要があります。データがデータベースに保存されている場合、リクエストごとにデータベースにクエリを実行する必要があり、これはデータベース設計とシステム設計の両方にとって大きな課題です。

2: リクエストの頻度が高すぎます。各リクエスト パケットには同じデータが含まれています。これは PC にとっては大したことではないかもしれませんが、モバイル クライアントにとっては最適な解決策ではありません。特に権限の判断に関しては、サーバーのロジックと効率もユーザーエクスペリエンスを低下させます。

  • COMET
    COMET テクノロジーは、単純なポーリングの欠点を改善し、ロング ポーリングを使用します。ロングポーリング方式では、サーバーは応答が完了した直後に接続を閉じるのではなく、各リクエスト中に一定期間接続を開いたままにします。この利点は、接続が開いている間、サーバーによって生成されたデータ更新をタイムリーにブラウザに返すことができることです。以前の長い接続が閉じられると、ブラウザはすぐに新しい長い接続を開いてリクエストを続行します。ただし、COMET テクノロジーの実装には、サーバー側とブラウザー側の両方でサードパーティ ライブラリのサポートが必要です。

現在、ほとんどの Web アプリには次のような Ajax が搭載されています。

HTML5 サーバープッシュサーバー送信イベント
上記の 4 つの異なるテクノロジーの包括的な比較。単純なポーリングは、それ自体に欠陥があるため推奨されません。 COMET テクノロジーは HTML 5 標準の一部ではないため、標準準拠の観点からその使用は推奨されません。 WebSocket 仕様とサーバー プッシュ テクノロジは両方とも HTML 5 標準のコンポーネントであり、主流のブラウザでネイティブ サポートを提供することが推奨されています。ただし、WebSocket 仕様はより複雑で、複雑な双方向データ通信を必要とするシナリオに適しています。単純なサーバー データ プッシュ シナリオの場合は、サーバー プッシュ イベントを使用するだけで十分です。

データベースのプッシュは次のようになります。データソースに新しいデータがあると、クライアントのリクエストを待たずにすぐにクライアントに送信されます。この新しいデータは、最新のニュース、最新の株価、友人からのチャット メッセージ、天気予報などです。

HTML5 サーバープッシュサーバー送信イベント

データのプルとプッシュの機能は同じで、ユーザーは新しいデータを取得します。ただし、データプッシュにはいくつかの利点があります。 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(&#39;result&#39;);        if (typeof (EventSource) !== &#39;undefined&#39;) {            //创建事件源
            var source = new EventSource(&#39;test.php&#39;);            //监听事件源发送过来的数据
            source.onmessage = function(event){
                result.innerHTML +=event.data +&#39;<br>&#39;;
            }
        }else{
            result.innerHTML += "您的浏览器不支持server sent Event";
        }    </script></body></html>
ログイン後にコピー
ログイン後にコピー
<?php 
    //指定发送事件流的MIME为text/event-stream
    header(&#39;Content-Type:text/event-stream&#39;);    //不缓存服务端发送的数据
    header(&#39;Cache-Control:no-cache&#39;);    //指定服务器发送的事件名
    echo "event:test\n\n";    // 定义服务器向客户端发送的数据
    echo "data:服务器当前时间为:".date(&#39;Y-m-d H:i:s&#39;)."\n\n";    //向客户端发送数据流
    flush(); ?>
ログイン後にコピー
ログイン後にコピー
  • ヘッダー「Content-Type」を「text/」に設定します。イベントストリーム"

  • ページがキャッシュされないことを規定します

  • 出力送信日 (常に "data: " で始まります)

  • 出力データを Web ページに更新します

プッシュされた情報の 1 つが終了フラグとして「nn」を使用していることに注意してください。テスト後、「nn」が終了フラグとして使用されていない場合、クライアントはプッシュされた値を受け取ることができません。また、特別なステートメントを作成する必要があります。プッシュされる情報の形式は "data:contentnn" でなければなりません。それ以外の場合は。 。 。
HTML5 サーバープッシュサーバー送信イベント

イベント ストリームの形式

イベント ストリームは単なるテキスト データ ストリームであり、テキストは UTF-8 形式でエンコードされる必要があります。コロンで始まる行はコメントです。行は無視されます。

各メッセージは複数のフィールドで構成され、各フィールドはフィールド名、コロン、フィールド値で構成されます。

フィールド

  • event Event type。このフィールドが指定されている場合、クライアントがメッセージを受信すると、現在の EventSource オブジェクトでイベントがトリガーされます。イベント タイプは、フィールドのフィールド値です。addEventListener() メソッドを使用して、現在のイベントをリッスンできます。 EventSource オブジェクト。メッセージにイベント フィールドがない場合、メッセージのデータ フィールドのイベント処理関数がトリガーされます。複数のデータ フィールドが含まれる場合、クライアントはフィールド値として改行文字を使用して文字列に連結されます。

  • id イベント ID は、現在の EventSource の内部プロパティ「最後のイベント ID」のプロパティ値になります。 object.

  • retry 再接続時間 (ミリ秒単位) を指定する整数値。
    上記で指定したフィールド名を除き、他のすべてのフィールド名は無視されます。 Chrome は 3 秒ごとにクライアントにプッシュされますが、FF は 5 秒ごとにプッシュされます。

  • 注: テキスト行にコロンが含まれていない場合、テキスト行全体がフィールド名に解析され、そのフィールド値は空になります。
    EventSource オブジェクトによって提供される標準イベント

名前

説明

イベント処理メソッドonopen
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(&#39;result&#39;);        if (typeof (EventSource) !== &#39;undefined&#39;) {            //创建事件源
            var source = new EventSource(&#39;test.php&#39;);            //监听事件源发送过来的数据
            source.onmessage = function(event){
                result.innerHTML +=event.data +&#39;<br>&#39;;
            }

            source.onopen = connectionOpen;
            source.onclose = connectionClose;            function connectionOpen(){
                if (source.readyState == 0) {
                    result.innerHTML +=&#39;未建立连接<br>&#39;;
                }                if (source.readyState == 1) {
                    result.innerHTML +=&#39;连接成功<br>&#39;;
                }
            }            function connectionClose(){
                result.innerHTML += "关闭连接,readyState属性值为:" + source.readyState + &#39;<br>&#39;;
            }            function closeCnt(){
                source.close();
                result.innerHTML += "断开连接,readyState属性值为:" + source.readyState + &#39;<br>&#39;;
            }
        }else{
            result.innerHTML += "您的浏览器不支持server sent Event";
        }    </script></body></html>
ログイン後にコピー
ログイン後にコピー

HTML5 サーバープッシュサーバー送信イベント

在指定 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(&#39;result&#39;);        if (typeof (EventSource) !== &#39;undefined&#39;) {            //创建事件源
            var source = new EventSource(&#39;test.php&#39;);            //自定义事件源发送过来的数据,事件名和php中事件名对应
            source.addEventListener(&#39;myevent&#39;, &#39;updateRequests&#39;, false);            // source.onmessage = function() {
            //  result.innerHTML = event.data + &#39;<br>&#39;;
            // }
            function updateRequests(event){
                result.innerHTML = event.data + &#39;<br>&#39;;
            }
        }else{
            result.innerHTML += "您的浏览器不支持server sent Event";
        }    </script></body></html>
ログイン後にコピー
ログイン後にコピー
<?php 
    //指定发送事件流的MIME为text/event-stream
    header(&#39;Content-Type:text/event-stream&#39;);    //不缓存服务端发送的数据
    header(&#39;Cache-Control:no-cache&#39;);    //指定服务器发送的事件名
    echo "event:myevent\n\n";    // 定义服务器向客户端发送的数据
    echo "data:服务器当前时间为:".date(&#39;Y-m-d H:i:s&#39;)."\n\n";    //向客户端发送数据流
    flush(); ?>
ログイン後にコピー
ログイン後にコピー

前端是HTML5,后端可以是PHP, JSP, Node.js, Asp.net等应用。

服务器推送事件(Server-sent Events)是 HTML 5 规范中的一个组成部分,可以用来从服务端实时推送数据到浏览器端。相对于与之类似的 COMET 和 WebSocket 技术来说,服务器推送事件的使用更简单,对服务器端的改动也比较小。对于某些类型的应用来说,服务器推送事件是最佳的选择。

  • WebSocket
    在介绍 HTML 5 服务器推送事件之前,首先介绍一些上面提到的几种服务器端数据推送技术。第一种是 WebSocket。WebSocket 规范是 HTML 5 中的一个重要组成部分,已经被很多主流浏览器所支持,也有不少基于 WebSocket 开发的应用。正如名称所表示的一样,WebSocket 使用的是套接字连接,基于 TCP 协议。使用 WebSocket 之后,实际上在服务器端和浏览器之间建立一个套接字连接,可以进行双向的数据传输。WebSocket 的功能是很强大的,使用起来也灵活,可以适用于不同的场景。不过 WebSocket 技术也比较复杂,包括服务器端和浏览器端的实现都不同于一般的 Web 应用。

  • 轮询
    除了 WebSocket 之外,其他的实现方式是基于 HTTP 协议来达到实时推送的效果。第一种做法是简易轮询,即浏览器端定时向服务器端发出请求,来查询是否有数据更新。这种做法比较简单,可以在一定程度上解决问题。不过对于轮询的时间间隔需要进行仔细考虑。轮询的间隔过长,会导致用户不能及时接收到更新的数据;轮询的间隔过短,会导致查询请求过多,增加服务器端的负担。

HTML5 サーバープッシュサーバー送信イベント
缺点:

1:轮询是由客户端发起的,那么在服务端就不能判别我要推送的内容是否已经过期,因为我很难判断某个信息是否已经推送给全部的客户端,那么服务端就需要缓存大量的数据。如果数据保存在数据库,那么还要每次请求都需要查询数据库,这对数据库和系统设计都是一个很大的挑战。

2:请求的频率太高,每次的请求包中含有同样的数据,这对pc来说也许算不得什么,但是对于移动客户端来讲,这应该不是最佳的方案。尤其是遇到还要做权限判断的时候,那么服务端的逻辑和效率也会造成用户体验的降低。

  • COMET
    COMET 技术改进了简易轮询的缺点,使用的是长轮询。长轮询的方式在每次请求时,服务器端会保持该连接在一段时间内处于打开状态,而不是在响应完成之后就立即关闭。这样做的好处是在连接处于打开状态的时间段内,服务器端产生的数据更新可以被及时地返回给浏览器。当上一个长连接关闭之后,浏览器会立即打开一个新的长连接来继续请求。不过 COMET 技术的实现在服务器端和浏览器端都需要第三方库的支持。

现在Web App中,大都有Ajax,是这样子:

HTML5 サーバープッシュサーバー送信イベント
综合比较上面提到的 4 种不同的技术,简易轮询由于其本身的缺陷,并不推荐使用。COMET 技术并不是 HTML 5 标准的一部分,从兼容标准的角度出发,也不推荐使用。WebSocket 规范和服务器推送技术都是 HTML 5 标准的组成部分,在主流浏览器上都提供了原生的支持,是推荐使用的。不过 WebSocket 规范更加复杂一些,适用于需要进行复杂双向数据通讯的场景。对于简单的服务器数据推送的场景,使用服务器推送事件就足够了。

基于数据推送是这样的,当数据源有新数据,它马上发送到客户端,不需要等待客户端请求。这些新数据可能是最新闻,最新股票行情,来自朋友的聊天信息,天气预报等。

HTML5 サーバープッシュサーバー送信イベント

数据拉与推的功能是一样的,用户拿到新数据。但数据推送有一些优势。 你可能听说过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(&#39;result&#39;);        if (typeof (EventSource) !== &#39;undefined&#39;) {            //创建事件源
            var source = new EventSource(&#39;test.php&#39;);            //监听事件源发送过来的数据
            source.onmessage = function(event){
                result.innerHTML +=event.data +&#39;<br>&#39;;
            }
        }else{
            result.innerHTML += "您的浏览器不支持server sent Event";
        }    </script></body></html>
ログイン後にコピー
ログイン後にコピー
<?php 
    //指定发送事件流的MIME为text/event-stream
    header(&#39;Content-Type:text/event-stream&#39;);    //不缓存服务端发送的数据
    header(&#39;Cache-Control:no-cache&#39;);    //指定服务器发送的事件名
    echo "event:test\n\n";    // 定义服务器向客户端发送的数据
    echo "data:服务器当前时间为:".date(&#39;Y-m-d H:i:s&#39;)."\n\n";    //向客户端发送数据流
    flush(); ?>
ログイン後にコピー
ログイン後にコピー
  • ヘッダー「Content-Type」を「text/」に設定します。イベントストリーム"

  • ページがキャッシュされないことを規定します

  • 出力送信日 (常に "data: " で始まります)

  • 出力データを Web ページに更新します

プッシュされた情報の 1 つが終了フラグとして「nn」を使用していることに注意してください。テスト後、「nn」が終了フラグとして使用されていない場合、クライアントはプッシュされた値を受け取ることができません。また、特別なステートメントを作成する必要があります。プッシュされる情報の形式は "data:contentnn" でなければなりません。それ以外の場合は。 。 。
HTML5 サーバープッシュサーバー送信イベント

イベント ストリームの形式

イベント ストリームは単なるテキスト データ ストリームであり、テキストは UTF-8 形式でエンコードされる必要があります。コロンで始まる行はコメントです。行は無視されます。

各メッセージは複数のフィールドで構成され、各フィールドはフィールド名、コロン、フィールド値で構成されます。

フィールド

  • event Event type。このフィールドが指定されている場合、クライアントがメッセージを受信すると、現在の EventSource オブジェクトでイベントがトリガーされます。イベント タイプは、フィールドのフィールド値です。addEventListener() メソッドを使用して、現在のイベントをリッスンできます。 EventSource オブジェクト。メッセージにイベント フィールドがない場合、メッセージのデータ フィールドのイベント処理関数がトリガーされます。複数のデータ フィールドが含まれる場合、クライアントはフィールド値として改行文字を使用して文字列に連結されます。

  • id イベント ID は、現在の EventSource の内部プロパティ「最後のイベント ID」のプロパティ値になります。 object.

  • retry 再接続時間 (ミリ秒単位) を指定する整数値。
    上記で指定したフィールド名を除き、他のすべてのフィールド名は無視されます。 Chrome は 3 秒ごとにクライアントにプッシュされますが、FF は 5 秒ごとにプッシュされます。

  • 注: テキスト行にコロンが含まれていない場合、テキスト行全体がフィールド名に解析され、そのフィールド値は空になります。
    EventSource オブジェクトによって提供される標準イベント

名前

説明

イベント処理メソッドonopen
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(&#39;result&#39;);        if (typeof (EventSource) !== &#39;undefined&#39;) {            //创建事件源
            var source = new EventSource(&#39;test.php&#39;);            //监听事件源发送过来的数据
            source.onmessage = function(event){
                result.innerHTML +=event.data +&#39;<br>&#39;;
            }

            source.onopen = connectionOpen;
            source.onclose = connectionClose;            function connectionOpen(){
                if (source.readyState == 0) {
                    result.innerHTML +=&#39;未建立连接<br>&#39;;
                }                if (source.readyState == 1) {
                    result.innerHTML +=&#39;连接成功<br>&#39;;
                }
            }            function connectionClose(){
                result.innerHTML += "关闭连接,readyState属性值为:" + source.readyState + &#39;<br>&#39;;
            }            function closeCnt(){
                source.close();
                result.innerHTML += "断开连接,readyState属性值为:" + source.readyState + &#39;<br>&#39;;
            }
        }else{
            result.innerHTML += "您的浏览器不支持server sent Event";
        }    </script></body></html>
ログイン後にコピー
ログイン後にコピー

HTML5 サーバープッシュサーバー送信イベント

在指定 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(&#39;result&#39;);        if (typeof (EventSource) !== &#39;undefined&#39;) {            //创建事件源
            var source = new EventSource(&#39;test.php&#39;);            //自定义事件源发送过来的数据,事件名和php中事件名对应
            source.addEventListener(&#39;myevent&#39;, &#39;updateRequests&#39;, false);            // source.onmessage = function() {
            //  result.innerHTML = event.data + &#39;<br>&#39;;
            // }
            function updateRequests(event){
                result.innerHTML = event.data + &#39;<br>&#39;;
            }
        }else{
            result.innerHTML += "您的浏览器不支持server sent Event";
        }    </script></body></html>
ログイン後にコピー
ログイン後にコピー
<?php 
    //指定发送事件流的MIME为text/event-stream
    header(&#39;Content-Type:text/event-stream&#39;);    //不缓存服务端发送的数据
    header(&#39;Cache-Control:no-cache&#39;);    //指定服务器发送的事件名
    echo "event:myevent\n\n";    // 定义服务器向客户端发送的数据
    echo "data:服务器当前时间为:".date(&#39;Y-m-d H:i:s&#39;)."\n\n";    //向客户端发送数据流
    flush(); ?>
ログイン後にコピー
ログイン後にコピー

前端是HTML5,后端可以是PHP, JSP, Node.js, Asp.net等应用。

 以上就是Html5 服务端推送 Server-Sent Event的内容,更多相关内容请关注PHP中文网(www.php.cn)!


ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート