java - 如何处理套接字断开和心跳消息?
问题描述
我想要做什么
我有一个有玩家的大厅,当有人离开大厅时,我想为每个客户更新它,以便显示实际的玩家列表。
我做了什么
为了避免从前端发送到后端的周期性请求,我决定使用web sockets
. 当有人离开大厅时,请求被发送到 REST api,然后后端在收到此请求后,执行所有业务逻辑,然后使用套接字“戳”这个大厅,以更新大厅中的所有客户端。
我的问题
一切正常,除了用户关闭浏览器或选项卡的情况,因为在这种情况下我无法发送请求。beforeunload
(据我所知,使用 javascript 和事件、onDestroy()
方法等是不可能做到的。)
我的问题
是否可以在服务器端检查是否有任何套接字断开连接,如果是,那么我该怎么做?我也尝试使用heartbeat
从前端发送到后端的消息,但我不知道如何heartbeat
在服务器端处理此消息。
服务器端(春季启动)
@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并在收到此类事件时向其他客户端发送消息。
当使用简单消息传递协议(例如 STOMP)作为 WebSocket 子协议的 WebSocket 客户端会话关闭时引发的事件。请注意,对于单个会话,此事件可能会多次引发,因此事件使用者应该是幂等的并忽略重复事件。
还有其他类型的事件。
推荐阅读
- css - @use 规则在使用 sublime text 3 的 gulp-sass 中不起作用
- r - 你如何重塑数据从宽到长?目前,我收到一个错误
- sql - 如果条件为真,SQL/HQL 写入表
- vector - 预期枚举`std::result::Result`,找到结构`std::vec::Vec`
- java - 如何将 Java 程序转换为 Python
- javascript - 如何使用 JavaScript 计算文本文件的每个后续行之间的差异?
- javascript - 在多个 API 请求后如何解决一个 Promise?
- java - Sonarqube 与 Gitlab CI 集成 - 无法访问 SonarQube 服务器
- go - Go/Golang 中的特殊 base64 实现(如 Drupal 的 PhpassHashedPassword::base64Encode())
- python - 我收到此错误 n_components=1000 must be between 0 and min(n_samples, n_features)=2 with svd_solver='full'