首页 > 解决方案 > Javascript 服务器端事件:多个客户端监听单个服务器实例

问题描述

我想用多个客户端监听一个服务器实例来实现服务器端事件。当我的客户连接时,他们会创建一个新的服务器实例。我希望他们都听同一个实例。

以下片段描述了服务器,Client1 侦听“Ping”,Client2 侦听“Pong”。运行时,每个客户端都会创建一个新实例,如在浏览器中生成并显示的随机密钥所示。我的目标是让它们 bot 监听到同一个实例。我已经看了好几个小时,找到了很多信息并使用了她的库,但我宁愿只使用本机。这是在包括 bootstrap、jquery、socket.io 和其他库的 FreePBX 环境中运行的。

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 $Key 是不同的,所以它们显然是不同的实例。(由于某种原因,它们都没有出现在 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 的现有实例,该实例将作为守护进程运行并向所有客户端广播。我怎样才能做到这一点?

标签: javascriptserver-sent-events

解决方案


这正是我所需要的。所以现在我有我自己的用 PHP 和客户端库编写的服务器,可以通过 ws:// wss:// tcp:// ssl:// 处理连接

看看 https://github.com/napengam/phpWebSocketServer


推荐阅读