簡體   English   中英

如何區分不同服務器發送的事件偵聽器?

[英]how to differentiate between different server sent event listeners?

我有一個應用程序,其中不同的用戶監聽服務器發送的事件源以獲取定期響應。我打算從服務器發送響應,並以json格式發送相應的ID和數據。在客戶端,每個客戶端在數據到達時檢查是否找到匹配的ID它會處理數據,否則會忽略它。但是這種方法的缺點是每個用戶都從定期更新中獲取數據,即使它不是針對他們的。我閱讀了一些有關sse的文章,但找不到任何相關信息。

我的問題是使用服務器端事件,是否可以通過任何方式將響應發送給特定的偵聽器?

基於問題澄清的UPDATE :如何停止客戶端接收不適合它的SSE消息。

最好的方法是不發送它。 在服務器端過濾消息。 (正如我的答案的前面部分所述,這很容易,因為每個SSE連接已經有一個專用的服務器進程來決定要發送什么數據。) 這種方法在所有方面 (CPU /內存,網絡帶寬,安全性,隱私,程序員的努力)。

替代方法是在客戶端對其進行過濾,並且有兩種方法可以執行此操作。 一種是將json數據發送到客戶端。 在您的onMessage()處理函數中,使用這些字段之一來確定此消息是否適用於此客戶端。

另一種方法是使用SSE的event:字段,然后偵聽該消息:

es = new EventSource(...);
es.addEventListener("forUser123", function(e) {
  //Process their data here
  }, false);

在發送data:字段之前,將在服務器上設置event:forUser123標頭。 (但是,如果您必須麻煩添加一個額外的標頭,最好過濾此時發送的消息。)


原始答案

您想要做的事情(特定於客戶端)很容易,而您認為服務器發送事件的工作方式(廣播)則更加困難。

與服務器的每個EventSource連接都是一個專用套接字。 因此,它通過與Web服務器的任何其他連接一樣來進行連接,唯一的區別是套接字沒有關閉,而是保持打開狀態,以便服務器可以繼續發送數據。 這也意味着服務器上有一個專用的進程或線程來處理要發送到該客戶端的消息。

因此,服務器知道每個用戶是誰(假設他們使用會話cookie來標識自己),並可以選擇發送該客戶端的數據。

旁白:為什么廣播更難? 假設您有100個已連接的SSE客戶端-您實際上正在運行100個獨立的服務器進程。 要向所有100個廣播一條消息,您首先必須告訴這100個服務器端進程什么是消息,以便它們可以繼續傳遞。 您可以使用上游套接字執行此操作,或者他們可以定期輪詢“ messagesToSendToEveryone”數據庫表以查看是否添加了新內容。

我要做的是注冊用戶/要求用戶登錄並返回唯一的身份驗證密鑰。使用此密鑰作為事件名稱,事件監聽器在注冊/登錄$ 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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM