WebSocket 心跳机制
通过心跳保持 WebSocket 连接活跃并检测连接状态
问题
WebSocket 中的心跳机制是为了解决什么问题?
解答
WebSocket 心跳机制主要解决两个问题:
1. 防止连接超时断开
服务端通常会设置连接超时时间,如果长时间没有数据传输,连接会被自动断开。通过定时发送心跳消息,可以让服务端知道连接仍然活跃,避免超时断线。
2. 检测连接健康状态
在连接看似正常的情况下,服务端可能已经出现异常。通过心跳机制可以及时发现问题:
- 客户端定时发送心跳包(ping)
- 服务端收到后返回响应(pong)
- 如果在规定时间内没有收到响应,说明连接异常,需要重连
实现示例
class WebSocketClient {
constructor(url) {
this.url = url;
this.ws = null;
this.heartbeatInterval = 30000; // 30秒
this.heartbeatTimer = null;
this.reconnectTimer = null;
this.pongTimeout = 5000; // 等待pong响应的超时时间
this.pongTimer = null;
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
console.log('连接成功');
this.startHeartbeat();
};
this.ws.onmessage = (event) => {
if (event.data === 'pong') {
clearTimeout(this.pongTimer);
}
// 处理其他消息
};
this.ws.onclose = () => {
console.log('连接断开');
this.stopHeartbeat();
this.reconnect();
};
this.ws.onerror = (error) => {
console.error('连接错误', error);
};
}
startHeartbeat() {
this.heartbeatTimer = setInterval(() => {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send('ping');
// 设置pong响应超时
this.pongTimer = setTimeout(() => {
console.log('心跳超时,重连');
this.ws.close();
}, this.pongTimeout);
}
}, this.heartbeatInterval);
}
stopHeartbeat() {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = null;
}
if (this.pongTimer) {
clearTimeout(this.pongTimer);
this.pongTimer = null;
}
}
reconnect() {
this.reconnectTimer = setTimeout(() => {
console.log('尝试重连');
this.connect();
}, 3000);
}
close() {
this.stopHeartbeat();
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
}
if (this.ws) {
this.ws.close();
}
}
}
// 使用
const client = new WebSocketClient('ws://localhost:8080');
client.connect();
关键点
- 心跳机制通过定时发送消息防止连接因超时被服务端断开
- 通过 ping-pong 模式检测连接是否真正可用,而不仅仅是表面连接
- 如果在规定时间内未收到 pong 响应,应主动断开并重连
- 心跳间隔要小于服务端的超时时间,通常设置为超时时间的一半
- 断线重连时要清理所有定时器,避免内存泄漏
目录