web-dev-qa-db-ja.com

サーバーイベントでサーバーからクライアントに通知を送信する

無関係なAjax呼び出しを回避して、PHPを使用してサーバーからクライアントにメッセージを送信するにはどうすればよいですか。

アイデアは次のとおりです。

  1. ユーザー:アリスはサーバーに送信される変更を行います。

  2. 次に、サーバーはどのユーザーが最新ではないかを確認し、そうでない場合は、変更に関連する情報をボブ(この場合は最新ではない)に送信するためのコードを呼び出します。

ボブにメッセージを送信するにはどうすればよいですか?

14
user3765372

サーバー送信イベント を使用できます。

これらは、軽量で一方向のWebSocketの見過ごされがちな従兄弟です。基本的に、クライアントはサーバーからのメッセージを待つことができます(AJAXなどの別のチャネルを介して応答できます)。

クライアントコードの例:

var source = new EventSource('/newFile');

source.addEventListener('message', function(e) {
  // Use AJAX and pull new file here
}, false);

残念ながら、(もちろん) noIE supportEventSource HQ などのライブラリを使用して、クロスブラウザサーバー送信イベントをサポートします。これにより、悪魔のブラウザを処理する必要がなくなります。

22
secretformula

あなたが探しているのは、(現在)非常に一般的で、「リアルタイムWeb」と呼ばれることもあるものです。これは、サーバー側のコードに、接続されたクライアントにコンテンツをリアルタイムでプッシュさせる機能です。

これは、最新のブラウザ(およびサーバー)でサポートされているいくつかの新しいメカニズムと、実際にはそれを行うように設計されていないが、それを機能させるための「ハック」として使用できる他のメカニズムによって可能になります。

最初に理解する必要があるのは、要求しているのは(サーバーがクライアントにメッセージを「プッシュ」する)、Web(または少なくともhttp)がどのようになっているのか(またはより良いのはwas)動作するように意図されていました。従来のWebはステートレス、要求/応答、半二重です。クライアントは通信を開始し、サーバーへの接続を開き、サーバーは何かを提供し、接続は閉じられます。また、サーバーがWebクライアントにメッセージを送信する方法はありませんでした。クライアント(つまりブラウザー)は、逆モデル(リッスンするエンドポイントを提供する)をサポートし、効果的にサーバーになる必要があります。

これは、多かれ少なかれ、 WebSockets のような新しい標準が提供するものです(言及する価値のある別の標準は サーバー送信イベント(SSE) です;ただし、そのサポートはWebSocketよりもさらに不足しています、そして彼らは単一のメッセージを送信するよりもコンテンツを「ストリーミング」する傾向があるようです)。

HTTPとは異なり、WebSocketは全二重通信(どちらの当事者も開始できます)を提供します。これはあなたが探しているものです。 WebSocketプロトコルの正しいバージョン(一部のブラウザーには古いバグのある実装が存在します)は、Firefox 6、Safari 6、Google Chrome 14、Opera 12.10、およびInternet Explorer10に実装されています。

では、ブラウザがWebSocketをサポートしていない場合はどうなるでしょうか。あなたは私が前に述べたそれらの「トリック」を使わなければなりません。それらの「トリック」は プッシュテクノロジー のアンブレラに分類されます。

特に、一般的な手法はロングポーリングです。名前が示すように、それは「プッシュ」ではありません。長いポーリングはポーリング、つまり「プル」手法ですが、プッシュメカニズムをエミュレートすることができます。長いポーリングでは、クライアントは、HTTP/S要求(ポーリング)をはるかに遅い頻度で発行することを除いて、通常のAJAX呼び出しとまったく同じようにサーバーに情報を要求します。

接続時に、サーバー(サーバー、API:サーブレット、HTTPハンドラー、RESTコントローラーなど!これは通常、標準のAJAX呼び出しのサポートを提供するのと同じメカニズムです)すでに利用可能なアップデートがある場合は、いくつかの情報を送信します。新しいものがない場合は、空の応答を送信する代わりに、要求を開いたままにして、応答情報が利用可能になるのを待ちます。

「従来の」クライアントが開始したリクエストがありますが、サーバーが通信したいものが見つかるまで、それは「保留」になります。何かがあると、サーバーはクライアントに応答を送信し(HTTPチャネルを介して、まだ開いています!)、開いているHTTP要求を完了します。

他の手法(プラグインによって提供されるソケットの使用など-Silverlight、Javaアプレット、 Flash ..)を使用することもできますが、それらを悪用するには、正しいクライアント(ブラウザー/プラグインの組み合わせ)が必要です。 )。

もちろん、これらすべてを自分で実装することもできます。そして、を学習演習として試してみることをお勧めします。

本番コードでは、 SignalR (ASP.NETの場合) Ratchet (PHPの場合)、 など、これらすべての概念と手法をカプセル化したライブラリを使用することをお勧めします。 Signal.IO (node.jsの場合)、 Faye (Rubyの場合)....これらのライブラリの一部は複数の手法を実装し、クライアントに基づいて最適な手法を選択します。自動的に他のものに戻ります。彼らは本当にあなたに多くのトラブルを免れます!

15

コメントで述べたように、あなたが探しているテクノロジーは WebSockets です。これらは、サーバーとWebブラウジングクライアントの間にソケット(基本的な双方向パイプのUNIX用語)を作成するための方法です。

生のWebSocketAPIを使用できます。 Socket.IO のようなライブラリを使用して、厄介な詳細を抽象化することを好みます。

通常どおりにパッケージをインストールした後(ノードを使用していると仮定)、Socket.IOは、イベントやブロードキャストなど、さまざまな簡単な方法をアプリケーションに統合します。 クロスブラウザWebSocketのみ として使用することもできます(WebSocketをサポートしていないブラウザのフォールバックロングポーリングを実装します)。

あなたの場合、サーバー上でファイルが変更されるたびに、サーバーからクライアントにメッセージを送信する必要があります。

サーバー側の1つ(Node.js):

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('disconnect', function () { });

  // more stuff here
  if(somethingChanged) {
    socket.send(JSON.stringify({changed: true, file: 'file1.txt', newContent: 'Im fresh off the press yo!'});
  }
});

クライアントの場合:

<script>
  var socket = io('http://localhost/');
  socket.on('connect', function () {
    socket.send('anything-new');

    socket.on('message', function (msg) {
      if(JSON.parse(msg).changed) {
        // Do stuff here
      }
    });
  });
</script>

これは非常に簡単な例ですが、うまくいけば、始めるのに十分です。

8
secretformula