WebSocket 心跳机制

WebSocket 心跳用于保持连接和检测服务端状态

问题

WebSocket 中的心跳机制是为了解决什么问题?

解答

WebSocket 心跳机制主要解决两个问题:

1. 保持连接不被断开

服务端通常会设置连接超时时间,如果长时间没有数据传输,连接会被自动断开。通过定时发送心跳消息,可以让服务端知道连接仍然活跃,避免超时断线。

// 客户端心跳实现
let heartbeatTimer = null;

function startHeartbeat(ws) {
  heartbeatTimer = setInterval(() => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({ type: 'ping' }));
    }
  }, 30000); // 每 30 秒发送一次
}

function stopHeartbeat() {
  if (heartbeatTimer) {
    clearInterval(heartbeatTimer);
    heartbeatTimer = null;
  }
}

2. 检测服务端是否正常

心跳不仅是单向发送,还需要服务端响应。如果发送心跳后,服务端在规定时间内没有响应,说明连接可能已经断开或服务端异常,此时需要进行重连。

let ws = null;
let heartbeatTimer = null;
let heartbeatTimeout = null;

function connect() {
  ws = new WebSocket('ws://example.com');
  
  ws.onopen = () => {
    startHeartbeat();
  };
  
  ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    
    // 收到心跳响应,重置超时计时器
    if (data.type === 'pong') {
      clearTimeout(heartbeatTimeout);
    }
  };
  
  ws.onclose = () => {
    stopHeartbeat();
    // 3 秒后重连
    setTimeout(connect, 3000);
  };
}

function startHeartbeat() {
  heartbeatTimer = setInterval(() => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({ type: 'ping' }));
      
      // 设置超时检测,5 秒内未收到响应则认为连接异常
      heartbeatTimeout = setTimeout(() => {
        ws.close();
      }, 5000);
    }
  }, 30000);
}

function stopHeartbeat() {
  clearInterval(heartbeatTimer);
  clearTimeout(heartbeatTimeout);
}

关键点

  • 定时发送心跳消息,防止连接因超时被服务端断开
  • 心跳需要服务端响应,用于检测服务端是否正常工作
  • 如果心跳响应超时,应主动关闭连接并重连
  • 心跳间隔通常设置为 30 秒左右,响应超时设置为 5 秒左右