2013-06-13 41 views
9

Tôi mới sử dụng WebSockets.cách gửi thư đến kết nối websocket cụ thể bằng máy chủ java

Tôi đã thực hiện cuộc trò chuyện máy chủ-ứng dụng đơn giản trong WebSockets.

Và bây giờ tôi đang cố gắng tạo ứng dụng trò chuyện khách-chủ-khách.

Tôi có một câu hỏi mà trong máy chủ java làm thế nào chúng ta có thể gửi một tin nhắn đến kết nối WebSocket cụ thể.

Nếu người dùng-A muốn gửi thư đến Người dùng-B.

Sau đó, làm cách nào tôi có thể quản lý Người dùng B đang sử dụng kết nối này hoặc kết nối đó hoặc gửi thư đến kết nối cụ thể đó?

Tôi đang tìm kiếm quá nhiều cho điều này trên google nhưng không thể tìm thấy bất cứ điều gì tốt.

Trả lời

18

Bạn phải thiết kế kiến ​​trúc cho điều đó.

Khi khách hàng thiết lập kết nối với máy chủ (mở WebSocket), máy chủ phải giữ kết nối ở đâu đó (dù bạn đang xác định kết nối cụ thể với chương trình phụ trợ Java bạn đang sử dụng), trong cấu trúc dữ liệu điều đó sẽ phụ thuộc vào những gì bạn đang cố gắng làm. Một số nhận dạng tốt sẽ là một ID người dùng cung cấp (giống như một biệt hiệu chưa được một peer khác kết nối với cùng một máy chủ). Nếu không, chỉ cần sử dụng đối tượng socket như một mã định danh duy nhất và khi liệt kê những người dùng khác trên giao diện người dùng, hãy liên kết chúng với mã định danh duy nhất của chúng để khách hàng có thể gửi tin nhắn đến một người ngang hàng cụ thể.

A HashMap sẽ là lựa chọn tốt cho cấu trúc dữ liệu nếu khách hàng trò chuyện với một khách hàng cụ thể khác, vì bạn có thể ánh xạ ID duy nhất của ứng dụng đến ổ cắm và tìm mục nhập bằng O (1) trong bảng băm.

Nếu bạn muốn quảng bá một thông điệp từ một khách hàng cho tất cả các khách hàng khác, mặc dù một HashMap cũng sẽ làm việc khá tốt (với cái gì đó như HashMap.values()), bạn có thể sử dụng một đơn giản List, gửi tin nhắn gửi đến cho tất cả khách hàng kết nối trừ người gửi ban đầu. Tất nhiên, bạn cũng muốn loại bỏ một khách hàng khỏi cấu trúc dữ liệu khi bạn mất kết nối với nó, dễ dàng bằng cách sử dụng một WebSocket (khung Java bạn đang sử dụng sẽ gọi lại cho bạn khi một socket đóng).

Dưới đây là một (gần như đầy đủ) ví dụ sử dụng một WebSocket Jetty 9 (và 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)); 
    } 
} 

Mã này là tự giải thích. Về JSON định dạng và phân tích cú pháp, Jetty có một số tiện ích thú vị trong gói org.eclipse.jetty.util.ajax. Cũng cần lưu ý rằng nếu khung máy chủ WebSocket của bạn không an toàn, bạn sẽ cần phải đồng bộ hóa cấu trúc dữ liệu để đảm bảo không có hỏng dữ liệu (ở đây MyWebSocket.sockets).

+0

bạn có thể đề xuất cho tôi bất kỳ liên kết hoặc trang web nào ..... hoặc bất kỳ mã tham chiếu nào ... cách gửi id uniqe bất kỳ cách nào chúng tôi có thể đặt trong bản đồ ???? – manankhh

+0

Chắc chắn: xem câu trả lời đã cập nhật của tôi. – eepp

+1

cảm ơn câu trả lời của bạn thực sự hữu ích /// .... – manankhh

Các vấn đề liên quan