我有一个应用程序,其中不同的用户侦听服务器发送的事件源以进行定期响应。我打算从服务器发送带有相应Id和json格式数据的响应。在客户端,每个客户端在数据到达时检查匹配Id如果发现它处理数据,否则忽略它。但这种方法的缺陷是每个用户从定期更新中获取数据,即使它不适合他们。我读了一些关于sse的文章,但无法找到任何关于这个
我的问题是使用服务器端事件是否有任何方式向特定侦听器发送响应,如果是,如何。?
答案 0 :(得分:2)
UPDATE 基于问题澄清:如何阻止客户端接收不适合它的SSE消息。
最好的方法是不发送它。过滤服务器端的消息。 (正如我的回答的前面部分所解释的那样,这很简单,因为每个SSE连接都已经有一个专用的服务器进程决定要发送给它的数据。)这种方法在所有方面都是优越的(CPU /内存,网络带宽,安全性,隐私,程序员努力)。
另一种方法是在客户端过滤它,有两种方法可以做到这一点。一种是将json数据发送给客户端。在onMessage()
处理程序中,使用其中一个字段来确定此消息是否适用于此客户端。
另一个是使用SSE的event:
字段,然后听取该消息:
es = new EventSource(...);
es.addEventListener("forUser123", function(e) {
//Process their data here
}, false);
在发送event:forUser123
字段之前,将在服务器上设置data:
标头。 (但是,如果你不得不添加一个额外的标题,那么最好过滤你此时发送的消息。)
原始答案
您想要做的事情(特定于客户端)很容易,而您认为Server-Sent-Events有效(广播)的方式更难。
与服务器的每个EventSource
连接都是专用套接字。就像任何其他与Web服务器的连接一样,唯一的区别是套接字未关闭,但保持打开状态,以便服务器可以继续发送数据。这也意味着服务器上有一个专用进程或线程来处理要发送给该客户端的消息。
因此,服务器知道每个用户是谁(假设他们自己标识会话cookie),并且可以选择发送该客户端的数据。
旁白:为什么广播更难?假设你有100个连接的SSE客户端 - 你实际上有100个独立的服务器进程正在运行。要向所有100个广播单个消息,首先必须告知这100个服务器端进程消息是什么,以便它们可以传递它。您可以使用上游套接字执行此操作,也可以定期轮询" messagesToSendToEveryone"数据库表以查看是否添加了任何新内容。
答案 1 :(得分:0)
我所做的是注册用户/要求用户登录并返回唯一的标识密钥。使用此密钥作为事件名称事件监听器在注册/登录$ post();的回发成功功能中初始化。
所以基本上每个事件监听器都会监听一个唯一的事件。在服务器端,每个事件名称都会被广播,然后是数据,因此唯一的事件监听器只能获取针对它们的消息。
$.post( "chatReg.php", { xxx: xxxx, time: xxx}).done(function( data ) {
if((typeof(EventSource) !== "undefined")&&((localStorage.getItem("uname") !== null))) {
var source = new EventSource("XXXXXXXX.php");
source.addEventListener(localStorage.getItem("uname"), function(e) {
var data = JSON.parse(e.data);
$('div.chat-box-content').append('<div class="msgWrapper"><div class="msgwrapperleft"><div class="iconright"><img src="http://placehold.it/40X40"></img></div><div class="MessageRight">'+data.Message+ '</div> </div><p class="ArrivedTimeRight"><span ><span class="timeago" >'+CreateTimestamp()+'</span></span></p></div>');
}, false);
}
}
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header("refresh: 5;");
echo 'event: '.$row['SpecialId'];
echo PHP_EOL;
echo 'data: {"Message":"'.$row['Message'].'","xxxId":"'.$row['xxxId'].'"}';
echo PHP_EOL;
echo PHP_EOL;