讨论广场 问答详情
比如说,我需要和服务端保持长连接,定期发送心跳,断开时自动重连。请问像我说的这种场景,应该如何用 WebSocket 实现保活机制?
永亮同学 2025-09-12 14:31:18
137 评论 分享
鸿蒙问答专区鸿蒙课程学习

比如说,我需要和服务端保持长连接,定期发送心跳,断开时自动重连。请问像我说的这种场景,应该如何用 WebSocket 实现保活机制?
相关代码:

```ts
const ws = new WebSocket(url);
ws.onopen = ()=> setInterval(()=> ws.send('ping'), 30000);
ws.onclose = ()=> reconnect();
```


 

137 评论 分享
写回答
全部评论(1)
1 楼

WebSocket 保活机制实现及代码优化
一、WEBSOCKET 保活机制实现方法
心跳机制(Heartbeat)
客户端定期发送心跳包(如ping帧),服务器回复pong帧确认连接活性

实现代码:


    

      

        
TypeScript

      

      

        setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: "heartbeat" })); // 发送心跳包
  }
}, 30000); // 每30秒发送一次

        
      

      
    

  
自动重连(Reconnection)
监听onclose事件,在连接断开时触发重连逻辑

采用指数退避策略避免频繁重连:


    

      

        
TypeScript

      

      

        let reconnectDelay = 1000; // 初始重连延迟1秒
function reconnect() {
  setTimeout(() => {
    initWebSocket();
    reconnectDelay = Math.min(reconnectDelay * 2, 30000); // 最大延迟30秒
  }, reconnectDelay);
}

        
      

      
    

  
连接状态监控
使用onerror监听异常,onopen重置重连计时器

心跳超时检测(未收到pong响应时强制重连):


    

      

        
TypeScript

      

      

        let heartbeatTimeout: NodeJS.Timeout;
ws.onmessage = (event) => {
  if (event.data.type === "pong") {
    clearTimeout(heartbeatTimeout); // 收到响应则清除超时器
  }
};

        
      

      
    

  
二、TYPESCRIPT 代码优化建议
参考代码:


    

      

        
TypeScript

      

      

        // 原始代码存在隐式any类型和错误处理缺失
server.on("upgrade", (req, socket) => {
  if (req.headers["upgrade"] !== "websocket") {
    socket.end("HTTP/1.1 400 Bad Request");
    return;
  }
  // ...握手逻辑
});

        
      

      
    

  
优化方案:
类型安全强化

    

      

        
TypeScript

      

      

        // 明确header类型
interface WebSocketHeaders {
  upgrade: string;
  'sec-websocket-key': string;
}

server.on("upgrade", (req: IncomingMessage & { headers: WebSocketHeaders }, socket: Duplex) => {
  if (req.headers.upgrade?.toLowerCase() !== "websocket") {
    socket.write("HTTP/1.1 400 Bad Request\r\n\r\n");
    socket.destroy(); // 显式销毁连接
    return;
  }
});

        
      

      
    

  
心跳处理集成

    

      

        
TypeScript

      

      

        // 服务器端心跳响应
ws.on('message', (data: Buffer) => {
  const message = JSON.parse(data.toString());
  if (message.type === "heartbeat") {
    ws.send(JSON.stringify({ type: "pong" })); // 响应心跳
  }
});

        
      

      
    

  
容错机制增强

    

      

        
TypeScript

      

      

        // 添加异常捕获和资源清理
ws.on('error', (error: Error) => {
  console.error(`WebSocket Error: ${error.message}`);
  ws.close(1011, 'Server Error'); // 规范的状态码
});

// 连接关闭时释放资源
ws.on('close', () => clearInterval(heartbeatInterval));

        
      

      
    

  
重连封装示例(客户端)

    

      

        
TypeScript

      

      

        class WebSocketClient {
  private reconnectAttempts = 0;
  
  connect(url: string) {
    const ws = new WebSocket(url);
    
    ws.onclose = () => {
      const delay = Math.min(1000 * 2 ** this.reconnectAttempts, 30000);
      setTimeout(() => this.connect(url), delay);
      this.reconnectAttempts++;
    };
  }
}

        
      

      
    

  
三、关键优化点总结
保活机制完整性
实现双向心跳检测(客户端发ping,服务端回pong)

心跳超时阈值建议:15-30秒(根据网络环境调整)

重连策略优化
指数退避避免服务端压力

最大重连间隔不超过30秒

资源管理
显式清除定时器(clearInterval/clearTimeout)

使用规范WebSocket关闭代码(如 1011表示服务端错误)

异常边界处理
消息解析添加try/catch

网络错误时触发降级重连

2025-09-12 15:59:54