|
|
@@ -164,38 +164,7 @@ public class WebSocketServer {
|
|
|
}
|
|
|
|
|
|
|
|
|
- /**
|
|
|
- * 新增:定时发送Ping包(心跳核心)
|
|
|
- * 每20秒给所有在线客户端发一次Ping,触发客户端回复Pong
|
|
|
- */
|
|
|
- @Scheduled(fixedRate = HEARTBEAT_INTERVAL)
|
|
|
- public void sendPingToAllClients() {
|
|
|
- long currentTime = System.currentTimeMillis();
|
|
|
- for (WebSocketServer webSocket : webSockets) {
|
|
|
- Session session = webSocket.session;
|
|
|
- String userId = webSocket.userId;
|
|
|
- try {
|
|
|
- if (session.isOpen()) {
|
|
|
- // 发送Ping包(WebSocket标准操作,客户端会自动回复Pong)
|
|
|
- session.getBasicRemote().sendPing(ByteBuffer.wrap(new byte[0]));
|
|
|
- log.debug("【websocket心跳】给用户ID: {} 发送Ping包", userId);
|
|
|
-
|
|
|
- // 检查是否超过Pong超时(如果10秒内没收到Pong,说明客户端失联,主动断开)
|
|
|
- long lastPong = lastPongTime.getOrDefault(userId, 0L);
|
|
|
- if (currentTime - lastPong > PONG_TIMEOUT) {
|
|
|
- log.warn("【websocket心跳】用户ID: {} 超过Pong超时,主动断开连接", userId);
|
|
|
- session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "Pong timeout"));
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("【websocket心跳】给用户ID: {} 发送Ping失败,主动清理连接", userId, e);
|
|
|
- // 发送失败时,清理无效连接
|
|
|
- sessionPool.remove(userId);
|
|
|
- webSockets.remove(webSocket);
|
|
|
- lastPongTime.remove(userId);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
|
|
|
@Scheduled(fixedRate = 30000) // 每30秒执行一次
|
|
|
public void cleanInvalidSessions() {
|