2013-06-13 38 views
9

我是新來的WebSockets。如何發送消息到特定的websocket連接使用java服務器

我已經作出的WebSockets一個簡單的服務器 - 客戶端聊天。

,現在我試圖讓客戶端 - 服務器 - 客戶端聊天應用。

我有一個問題,在Java服務器如何才能將消息發送到特定的WebSocket連接。

如果用戶-A想要發送消息給用戶-B。

那我怎麼才能管理該用戶B使用這樣或那樣的連接或將消息發送到特定的連接?

我尋找太多這對谷歌,但找不到什麼好東西。

回答

18

你必須爲此設計一個架構。

當客戶端與服務器建立連接(打開WebSocket)時,服務器必須將連接保持在某個位置(無論您如何識別與正在使用的Java後端的特定連接),數據結構這將取決於你想要做什麼。一個好的標識符應該是用戶提供的一個ID(就像一個暱稱,這個暱稱還沒有被另一個連接到同一個服務器的對等端選中)。否則,只需使用套接字對象作爲唯一標識符,並在前端列出其他用戶時,將它們與其唯一標識符相關聯,以便客戶端可以向特定對等方發送消息。

A HashMap如果客戶端要與另一個特定客戶端聊天,那麼這將是一個很好的選擇,因爲您可以將客戶端的唯一ID映射到套接字並在O(1)中找到條目,在一個哈希表中。

如果要播放從客戶端向所有其他客戶端的消息,雖然HashMap也工作得很好(有類似HashMap.values()),你可以使用一個簡單的List,除了送進來的消息發送給所有連接的客戶端原始發件人。

當然,當你失去與數據結構的連接時,你也希望從數據結構中刪除一個客戶端,這很容易使用WebSocket(當你關閉套接字時,你正在使用的Java框架應該給你回電)。

下面是一個使用Jetty 9的WebSocket(和JDK 7)(幾乎完全)例如:

package so.example; 
import java.io.IOException; 
import java.util.HashMap; 

import org.eclipse.jetty.websocket.api.Session; 
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; 
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; 
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; 
import org.eclipse.jetty.websocket.api.annotations.WebSocket; 

@WebSocket 
public class MyWebSocket { 
    private final static HashMap<String, MyWebSocket> sockets = new HashMap<>(); 
    private Session session; 
    private String myUniqueId; 

    private String getMyUniqueId() { 
     // unique ID from this class' hash code 
     return Integer.toHexString(this.hashCode()); 
    } 

    @OnWebSocketConnect 
    public void onConnect(Session session) { 
     // save session so we can send 
     this.session = session; 

     // this unique ID 
     this.myUniqueId = this.getMyUniqueId(); 

     // map this unique ID to this connection 
     MyWebSocket.sockets.put(this.myUniqueId, this); 

     // send its unique ID to the client (JSON) 
     this.sendClient(String.format("{\"msg\": \"uniqueId\", \"uniqueId\": \"%s\"}", 
       this.myUniqueId)); 

     // broadcast this new connection (with its unique ID) to all other connected clients 
     for (MyWebSocket dstSocket : MyWebSocket.sockets.values()) { 
      if (dstSocket == this) { 
       // skip me 
       continue; 
      } 
      dstSocket.sendClient(String.format("{\"msg\": \"newClient\", \"newClientId\": \"%s\"}", 
        this.myUniqueId)); 
     } 
    } 

    @OnWebSocketMessage 
    public void onMsg(String msg) { 
     /* 
     * process message here with whatever JSON library or protocol you like 
     * to get the destination unique ID from the client and the actual message 
     * to be sent (not shown). also, make sure to escape the message string 
     * for further JSON inclusion. 
     */ 
     String destUniqueId = ...; 
     String escapedMessage = ...; 

     // is the destination client connected? 
     if (!MyWebSocket.sockets.containsKey(destUniqueId)) { 
      this.sendError(String.format("destination client %s does not exist", destUniqueId)); 
      return; 
     } 

     // send message to destination client 
     this.sendClient(String.format("{\"msg\": \"message\", \"destId\": \"%s\", \"message\": \"%s\"}", 
       destUniqueId, escapedMessage)); 
    } 

    @OnWebSocketClose 
    public void onClose(Session session, int statusCode, String reason) { 
     if (MyWebSocket.sockets.containsKey(this.myUniqueId)) { 
      // remove connection 
      MyWebSocket.sockets.remove(this.myUniqueId); 

      // broadcast this lost connection to all other connected clients 
      for (MyWebSocket dstSocket : MyWebSocket.sockets.values()) { 
       if (dstSocket == this) { 
        // skip me 
        continue; 
       } 
       dstSocket.sendClient(String.format("{\"msg\": \"lostClient\", \"lostClientId\": \"%s\"}", 
         this.myUniqueId)); 
      } 
     } 
    } 

    private void sendClient(String str) { 
     try { 
      this.session.getRemote().sendString(str); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private void sendError(String err) { 
     this.sendClient(String.format("{\"msg\": \"error\", \"error\": \"%s\"}", err)); 
    } 
} 

代碼是自解釋的。關於JSON格式和解析,Jetty在包org.eclipse.jetty.util.ajax中有一些有趣的實用程序。

另請注意,如果您的WebSocket服務器框架不是線程安全的,則需要同步數據結構以確保沒有數據損壞(此處爲MyWebSocket.sockets)。

+0

你可以建議我任何鏈接或網站.....或任何參考代碼...這如何發送潮頭ID的我們怎樣才能把它在地圖???? – manankhh

+0

當然:看到我更新的答案。 – eepp

+1

謝謝你的答案,它真的有用/// .... – manankhh

相關問題