如何处理socket断开和心跳消息?
How to handle socket disconnection and heartbeat messages?
我想做什么
我有一个玩家大厅,当有人离开大厅时,我想为每个客户更新它,以便显示实际的玩家列表。
我做了什么
为了避免循环请求从前端发送到后端,我决定使用 web sockets
。当有人离开大厅时,请求被发送到 REST api,然后后端在收到此请求后执行所有业务逻辑,然后 "pokes" 这个大厅使用套接字来更新大厅中的所有客户端.
我的问题
除了用户关闭浏览器或选项卡的情况外,一切正常,因为在这种情况下我无法发送请求。 (据我所知,使用 javascript 和 beforeunload
事件、onDestroy()
方法等是不可能做到的。)
我的问题
是否可以在服务器端检查是否有任何套接字断开连接,如果是,我该怎么做?我还尝试使用从前端发送到后端的 heartbeat
,但我不知道如何在服务器端处理此 heartbeat
消息。
服务器端(Spring启动)
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguartion implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/api/socket")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
ThreadPoolTaskScheduler te = new ThreadPoolTaskScheduler();
te.setPoolSize(1);
te.setThreadNamePrefix("wss-heartbeat-thread-");
te.initialize();
config.enableSimpleBroker("/lobby")
.setHeartbeatValue(new long[]{0, 1000})
.setTaskScheduler(te);
}
}
@Controller
public class WebSocketController {
private final SimpMessagingTemplate template;
WebSocketController(SimpMessagingTemplate template) {
this.template = template;
}
public void pokeLobby(@DestinationVariable String lobbyName, SocketMessage message) {
this.template.convertAndSend("/lobby/"+lobbyName.toLowerCase(), message);
}
}
客户端
connectToLobbyWebSocket(lobbyName: string): void {
const ws = new SockJS(this.addressStorage.apiAddress + '/socket');
this.stompClient = Stomp.over(ws);
// this.stompClient.debug = null;
const that = this;
this.stompClient.connect({}, function () {
that.stompClient.subscribe('/lobby/' + lobbyName, (message) => {
if (message.body) {
that.socketMessage.next(message.body); // do client logic
}
});
});
}
您可以在您的应用程序中侦听 SessionDisconnectEvent 并在收到此类事件时向其他客户端发送消息。
Event raised when the session of a WebSocket client using a Simple Messaging Protocol (e.g. STOMP) as the WebSocket sub-protocol is closed.
Note that this event may be raised more than once for a single session and therefore event consumers should be idempotent and ignore a duplicate event.
还有其他类型events。
我想做什么
我有一个玩家大厅,当有人离开大厅时,我想为每个客户更新它,以便显示实际的玩家列表。
我做了什么
为了避免循环请求从前端发送到后端,我决定使用 web sockets
。当有人离开大厅时,请求被发送到 REST api,然后后端在收到此请求后执行所有业务逻辑,然后 "pokes" 这个大厅使用套接字来更新大厅中的所有客户端.
我的问题
除了用户关闭浏览器或选项卡的情况外,一切正常,因为在这种情况下我无法发送请求。 (据我所知,使用 javascript 和 beforeunload
事件、onDestroy()
方法等是不可能做到的。)
我的问题
是否可以在服务器端检查是否有任何套接字断开连接,如果是,我该怎么做?我还尝试使用从前端发送到后端的 heartbeat
,但我不知道如何在服务器端处理此 heartbeat
消息。
服务器端(Spring启动)
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguartion implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/api/socket")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
ThreadPoolTaskScheduler te = new ThreadPoolTaskScheduler();
te.setPoolSize(1);
te.setThreadNamePrefix("wss-heartbeat-thread-");
te.initialize();
config.enableSimpleBroker("/lobby")
.setHeartbeatValue(new long[]{0, 1000})
.setTaskScheduler(te);
}
}
@Controller
public class WebSocketController {
private final SimpMessagingTemplate template;
WebSocketController(SimpMessagingTemplate template) {
this.template = template;
}
public void pokeLobby(@DestinationVariable String lobbyName, SocketMessage message) {
this.template.convertAndSend("/lobby/"+lobbyName.toLowerCase(), message);
}
}
客户端
connectToLobbyWebSocket(lobbyName: string): void {
const ws = new SockJS(this.addressStorage.apiAddress + '/socket');
this.stompClient = Stomp.over(ws);
// this.stompClient.debug = null;
const that = this;
this.stompClient.connect({}, function () {
that.stompClient.subscribe('/lobby/' + lobbyName, (message) => {
if (message.body) {
that.socketMessage.next(message.body); // do client logic
}
});
});
}
您可以在您的应用程序中侦听 SessionDisconnectEvent 并在收到此类事件时向其他客户端发送消息。
Event raised when the session of a WebSocket client using a Simple Messaging Protocol (e.g. STOMP) as the WebSocket sub-protocol is closed. Note that this event may be raised more than once for a single session and therefore event consumers should be idempotent and ignore a duplicate event.
还有其他类型events。