ZeroMQを使用してこの問題を解決できます。
ZeroMQは、物事(スレッド、プロセス、さらには個別のマシン)を一緒に接続するための過給されたソケットを提供するライブラリです。
サーバーからクライアントにデータをプッシュしようとしていると思います。そのための良い方法は、EventSource API(ポリフィルが利用可能)を使用することです。
client.js
EventSourceを介してstream.phpに接続します。
var stream = new EventSource('stream.php');
stream.addEventListener('debug', function (event) {
var data = JSON.parse(event.data);
console.log([event.type, data]);
});
stream.addEventListener('message', function (event) {
var data = JSON.parse(event.data);
console.log([event.type, data]);
});
router.php
これは、着信メッセージをリッスンし、リッスンしているすべての人に送信する、長時間実行されるプロセスです。
<?php
$context = new ZMQContext();
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind("tcp://*:5555");
$pub = $context->getSocket(ZMQ::SOCKET_PUB);
$pub->bind("tcp://*:5556");
while (true) {
$msg = $pull->recv();
echo "publishing received message $msg\n";
$pub->send($msg);
}
stream.php
サイトに接続するすべてのユーザーは、独自のstream.phpを取得します。このスクリプトは長時間実行され、ルーターからのメッセージを待ちます。新しいメッセージを取得すると、このメッセージをEventSource形式で出力します。
<?php
$context = new ZMQContext();
$sock = $context->getSocket(ZMQ::SOCKET_SUB);
$sock->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, "");
$sock->connect("tcp://127.0.0.1:5556");
set_time_limit(0);
ini_set('memory_limit', '512M');
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
while (true) {
$msg = $sock->recv();
$event = json_decode($msg, true);
if (isset($event['type'])) {
echo "event: {$event['type']}\n";
}
$data = json_encode($event['data']);
echo "data: $data\n\n";
ob_flush();
flush();
}
すべてのユーザーにメッセージを送信するには、メッセージをルーターに送信するだけです。その後、ルーターはそのメッセージをすべてのリスニングストリームに配信します。次に例を示します。
<?php
$context = new ZMQContext();
$sock = $context->getSocket(ZMQ::SOCKET_PUSH);
$sock->connect("tcp://127.0.0.1:5555");
$msg = json_encode(array('type' => 'debug', 'data' => array('foo', 'bar', 'baz')));
$sock->send($msg);
$msg = json_encode(array('data' => array('foo', 'bar', 'baz')));
$sock->send($msg);
これは、リアルタイムプログラミングを行うためにnode.jsが必要ないことを証明するはずです。PHPはそれをうまく処理できます。
それとは別に、socket.ioはこれを行うための本当に良い方法です。また、ZeroMQを介してsocket.ioからPHPコードに簡単に接続できます。
も参照してください