События на стороне сервера Javascript: несколько клиентов прослушивают один экземпляр сервера - PullRequest
0 голосов
/ 18 ноября 2018

Я хочу реализовать события на стороне сервера, когда несколько клиентов прослушивают один экземпляр сервера.Когда мои клиенты подключаются, они создают новый экземпляр сервера.Я хочу, чтобы все они слушали один и тот же экземпляр.

Следующие фрагменты описывают сервер, Client1 прослушивает «Ping» и Client2 прослушивает «Pong. При запуске каждый клиент создает новый экземпляр, как показанослучайный ключ, сгенерированный и отображенный в браузере. Моя цель - заставить их бота слушать один и тот же экземпляр. Я часами смотрел в глаза и находил много информации и использовал другие библиотеки, но я бы предпочел просто использовать native. Это работает вFreePBX environemnt, который включает в себя начальную загрузку, jquery, socket.io и другие библиотеки.

sse-serv.php:

<?php
date_default_timezone_set("America/New_York");
header("Content-Type: text/event-stream");
$key = rand(1111, 9999); // a random counter
$counter=0;
while ($counter < 100) {
// 1 is always true, so repeat the while loop forever (aka event-loop)
  $curDate = date("Y-m-d H:i:s");
  $msg=array();
  $msg['count']=$counter;
  $msg['time']=$curDate;
  $msg['key']=$key;
  $json_msg=json_encode($msg);
  if ($ping) {
    echo "event: ping\ndata: $json_msg \n\n";
    $ping=false;
  } else {
    echo "event: pong\ndata: $json_msg \n\n";
    $ping=true;
  }
  $counter++;
  ob_end_flush();
  flush();
  if ( connection_aborted() ) break;
  sleep(1);
}
?>

Каждую секунду сервер альтернативно отправляет «Ping» или «Pong»"событие. Клиенты отображают именно то, что я ожидаю, за исключением того, что ключ RND $ является разницей, поэтому они явно разные экземпляры. (По какой-то причине ни один из них не отображается в ps aux | grep sse-serv).

sse-client1.php:

<?php
session_start();
require_once('include.php');
require_once('/etc/freepbx.conf');
$dt=date("Y-m-d H:i:s");
?>
<html>
<head>
   <meta charset="UTF-8">
   <title>Server-sent events demo</title>
</head>
<body>
  <button>Close the connection</button>
<script>

  var button = document.querySelector('button');
  var evtSource = new EventSource('sse-serv.php');
  console.log(evtSource.withCredentials);
  console.log(evtSource.readyState);
  console.log(evtSource.url);
  var eventList = document.querySelector('ul');
  evtSource.onopen = function() {
    console.log("Connection to server opened.");
  };
  evtSource.onmessage = function(e) {
    var newElement = document.createElement("li");
    newElement.textContent = "message: " + e.data;
    eventList.appendChild(newElement);
  };
  evtSource.onerror = function() {
    console.log("EventSource failed.");
  };
  button.onclick = function() {
    console.log('Connection closed');
    evtSource.close();
  };
evtSource.addEventListener("ping", function(e) {
var newElement = document.createElement("li");
  var today = new Date();
  var h = today.getHours();
  var m = today.getMinutes();
  var s = today.getSeconds();
  var ntime= h + ":" + m + ":" + s;
   var obj = JSON.parse(e.data);
newElement.innerHTML = "Key: " + obj.key + ping at " + obj.time + " Local time: " + ntime + " counter: " + obj.count;
eventList.appendChild(newElement);
}, false);
</script>
</body>
</html>

Client2 точно такой же, как client1, за исключением того, что он слушает «Pong» вместо «Ping».

Когда я запускаю их обоих клиентов одновременно, я получаю это:

Клиент1:

Key: 2642 ping at 2018-11-18 06:27:19 Local time: 6:27:19 counter: 1
Key: 2642 ping at 2018-11-18 06:27:21 Local time: 6:27:21 counter: 3
Key: 2642 ping at 2018-11-18 06:27:23 Local time: 6:27:23 counter: 5
Key: 2642 ping at 2018-11-18 06:27:25 Local time: 6:27:25 counter: 7
Key: 2642 ping at 2018-11-18 06:27:27 Local time: 6:27:27 counter: 9

Клиент2

Key: 1818 pong at 2018-11-18 06:27:18 Local time: 6:27:18 counter: 0
Key: 1818 pong at 2018-11-18 06:27:20 Local time: 6:27:20 counter: 2
Key: 1818 pong at 2018-11-18 06:27:22 Local time: 6:27:22 counter: 4
Key: 1818 pong at 2018-11-18 06:27:24 Local time: 6:27:24 counter: 6
Key: 1818 pong at 2018-11-18 06:27:26 Local time: 6:27:26 counter: 8

Этот вывод - именно то, что я хочу, кромеразличные ключи доказывают, что на каждом клиенте запущен отдельный экземпляр sse-serv.php.Мне нужно, чтобы они оба прослушали существующий экземпляр sse-serv.php, который будет работать как демон и транслироваться всем клиентам.Как я могу это сделать?

Ответы [ 3 ]

0 голосов
/ 18 ноября 2018

Каждый скрипт PHP по умолчанию полностью изолирован. Если вы просто хотите быстро создать прототип, я бы предложил использовать другую среду. В node.js все разделяется, и повторение вашего примера будет тривиальным.

Если PHP является обязательным требованием, и вы готовы потратить дополнительное время, не заставляйте PHP обрабатывать несколько соединений, а вместо этого перенесите аспект pub / sub вашего приложения на выделенный сервер. Существует множество систем типа pub / sub-like с хорошими клиентами PHP. Каждый с различными свойствами масштабируемости и сложности. С Redis довольно легко начать работу.

0 голосов
/ 22 ноября 2018

Это было именно то, что мне было нужно.Так что теперь у меня есть свой собственный сервер, написанный на PHP и клиентские библиотеки, который может обрабатывать соединения через ws: // wss: // tcp: // ssl: // Я использую этот сервер в настоящее время в веб-приложении в нашей интрасети.

Взгляните на https://github.com/napengam/phpWebSocketServer

0 голосов
/ 18 ноября 2018

РЕДАКТИРОВАТЬ: Я пропустил много деталей в этом ответе. Я упоминаю здесь WebSockets, потому что в конечном счете вы, вероятно, обнаружите, что вам требуется больше поддержки функций / гибкости, чем обеспечивает Server-Sent Events.

Вы добьетесь большего успеха с сервером WebSocket на PHP. Вы просто создали длительный процесс, который вызывается вашим веб-сервером как стандартный тип MIME PHP. Это означает, что для каждого запроса к конечной точке PHP (как вы понимаете) вы запускали новый экземпляр PHP. Скорее всего, ваш URL на странице PHP использует http:// ...

URL-адрес сервера веб-сокетов начинается с ws://. Это говорит серверу использовать единственный существующий запущенный процесс. Затем сервер веб-сокетов отслеживает все доступные «каналы» и передает их на эти каналы.

Самое быстрое решение для этого - использовать Ratchet WSS, найденный здесь: http://socketo.me

Это должно исправить тебя. Если вы предпочитаете писать свои собственные, вам доступно множество ресурсов.

...