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
).
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
Chắc chắn: xem câu trả lời đã cập nhật của tôi. – eepp
cảm ơn câu trả lời của bạn thực sự hữu ích /// .... – manankhh