2015-10-05 56 views
12

我想用Play2和Java實現一個基於WebSockets的解決方案。目前我沒有使用Actor Model進行併發管理。相反,它只是handling the WebSockets using callbacksJava - Play2是WebSockets實現所需的Actor?

問題是服務器無法將消息'廣播'到多個客戶端。例如,我需要所有活動的瀏覽器會話在通過客戶端觸發操作後接收簡單通知。相反,我只能在單個客戶端會話中模擬此操作。實際上,它只是作爲常規的Ajax請求/響應場景。

我的猜測是Play2的WebSockets解決方案&帶簡單回調的Java無法將消息廣播到所有連接的客戶端瀏覽器。

回撥服務器代碼

public static WebSocket<String> heartUpdate() { 
     return new WebSocket<String>() { 
      public void onReady(final WebSocket.In<String> in, 
        WebSocket.Out<String> out) { 
       in.onMessage(new Callback<String>() { 
        @Override 
        public void invoke(String event) throws Throwable { 
         Product product = Product.find.byId(Long.decode(event)); 
         // Other business stuff 
         out.write(entity.id + " " + decimalValue); 
        } 
       }); 
       in.onClose(new Callback0() { 
        @Override 
        public void invoke() throws Throwable { 

        } 
       }); 
       out.write(DELIM_USERID_REP); 
      } 
     }; 
    } 

路由條目

GET /repsocket controllers.Application.heartUpdate 

客戶端側

<script> 
    // Onto the WebSockets now 
    var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket; 
    var socket = new WS("@routes.Application.heartUpdate.webSocketURL(request)"); 

    var receiveEvent = function(event) { 
     alert(event.data); 
     // Notification badge visible with a common text 
     $('#notify').text(event.data); 
     $('#notify').addClass('visible'); 
    } 
     $('#heart').click(function(e) { 
      e.preventDefault(); 
      socket.send(@product.id); 
     }); 
    socket.onmessage = receiveEvent; 
    </script> 

在在上述情況下,動作觸發客戶端是成功從服務器接收消息的客戶端,而任何其他瀏覽器會話都不成功。

我沒有找到任何與Play2與Java對齊的文檔& WebSockets建議強制使用Actors與所有連接的活動客戶端保持一致的通信。

Question: Play2 with Java中的WebSockets是否應該使用Actor Model來實現,以將消息廣播到所有活動的客戶端會話?

編輯: 下面的截圖中反映出瀏覽器的2國,我在已經登錄到使用2個有效的用戶憑據。

理想情況下,WebSockets的服務器響應應該在兩個瀏覽器上創建相同的通知標誌。

enter image description here

+0

你有什麼錯誤? – 2015-10-05 16:44:17

+0

@nikpon沒有錯誤,來自服務器的消息只反映在一個瀏覽器會話中 - 觸發了請求而不是在任何其他連接的客戶端會話中 – PopoFibo

+0

您是如何獲得瀏覽器會話的? – 2015-10-05 16:53:10

回答

5

看着你發佈的代碼,看來問題是,你不保存到每個連接的引用,所以你可以稍後廣播消息。事情是這樣的:

// Just an example: does not deal with concurrency problems 
private static final Set<WebSocket.Out<String>> SOCKETS = new HashSet<>(); 

public static WebSocket<String> heartUpdate() { 
    return new WebSocket<String>() { 
     public void onReady(final WebSocket.In<String> in, 
        final WebSocket.Out<String> out) { 
      SOCKETS.add(out); 
      in.onMessage(new Callback<String>() { 
       @Override 
       public void invoke(String event) throws Throwable { 
        for(WebSocket.Out<String> s: SOCKETS) { 
         s.write("SOME MESSAGE");  
        } 
       } 
      }); 
      in.onClose(new Callback0() { 
       @Override 
       public void invoke() throws Throwable { 
        SOCKETS.remove(out); 
       } 
      }); 
     } 
    }; 
} 

您還可以使用角色建模這個問題:具有負責任的演員,以保持連接的跟蹤和應對新的套接字連接/關閉。

如果你想使用阿卡有some activator templates讓你開始。

+0

它實際上只在循環中進行過一次,實際上與原始問題的行爲相同 - 也許我錯過了更基本的東西 – PopoFibo

+0

劃痕,我測試它都是錯誤的。它實際上工作,非常感謝。我會把這個問題作爲一個開放的賞金來接受,併爲你的答案提供一些幫助。 – PopoFibo