2025.6.8
在 WebSocket 连接关闭前发送消息
是的,可以在 WebSocket 连接关闭前发送一条告别消息。以下是修改后的实现方式:
服务端修改 - Spring Boot WebSocket 处理器
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
public class MyWebSocketHandler extends TextWebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("连接建立: " + session.getId());
session.sendMessage(new TextMessage("欢迎连接到WebSocket服务器!"));
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String clientMessage = message.getPayload();
System.out.println("收到消息: " + clientMessage);
// 回复客户端
String reply = "服务器已收到: " + clientMessage;
session.sendMessage(new TextMessage(reply));
}
@Override
public void afterConnectionClosed(WebSocketSession session,
org.springframework.web.socket.CloseStatus status) throws Exception {
try {
// 在连接关闭前发送告别消息
if (session.isOpen()) {
session.sendMessage(new TextMessage("感谢使用,再见!"));
// 等待消息发送完成
Thread.sleep(100); // 短暂延迟确保消息发送
}
} catch (Exception e) {
System.err.println("发送告别消息时出错: " + e.getMessage());
} finally {
System.out.println("连接关闭: " + session.getId());
}
}
}
客户端修改 - HTML/JavaScript
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket测试</title>
<style>
/* 样式保持不变 */
</style>
</head>
<body>
<!-- 其他HTML内容保持不变 -->
<script>
// ... 其他代码保持不变 ...
// 连接关闭时
socket.onclose = function(event) {
addMessage("连接已关闭: " + event.reason);
};
// 添加一个手动关闭连接的按钮
function closeConnection() {
if (socket.readyState === WebSocket.OPEN) {
// 先发送一条关闭前的消息
socket.send("客户端准备关闭连接");
// 然后优雅地关闭连接
socket.close(1000, "客户端正常关闭");
}
}
// 在页面上添加关闭按钮
document.body.innerHTML += '<button onclick="closeConnection()">关闭连接</button>';
</script>
</body>
</html>
关键点说明
-
服务端关闭前发送消息:
- 在
afterConnectionClosed
方法中尝试发送告别消息 - 使用
session.isOpen()
检查连接是否仍然可用 - 添加短暂延迟确保消息发送完成
- 在
-
客户端优雅关闭:
- 先发送关闭通知消息
- 使用
socket.close()
方法并指定状态码和原因 - 状态码 1000 表示正常关闭
-
注意事项:
- 当连接正在关闭时,可能无法保证消息一定能送达
- 对于重要消息,最好在关闭前提前发送
- 生产环境中应考虑添加重试机制
更可靠的实现方式
如果需要在关闭连接前确保消息送达,可以这样修改:
@Override
public void afterConnectionClosed(WebSocketSession session,
CloseStatus status) throws Exception {
try {
// 在关闭前发送消息
String farewell = "感谢使用,再见!";
session.sendMessage(new TextMessage(farewell));
// 等待消息发送完成(最大等待时间)
for (int i = 0; i < 5 && session.isOpen(); i++) {
Thread.sleep(100);
}
} catch (Exception e) {
System.err.println("发送告别消息时出错: " + e.getMessage());
} finally {
System.out.println("连接关闭: " + session.getId() + ", 原因: " + status.getReason());
}
}
这样实现可以在连接关闭前尽可能确保告别消息被发送出去。