WebSocket需客户端和服务端协同实现心跳检测:客户端定时发轻量ping消息(如'{"t":"p"}'),服务端响应pong并维护lastPingTime,双方均设超时机制,客户端还需监听超时启动退避重连。

WebSocket 连接默认没有内置心跳机制,长时间无数据交互时,中间网络设备(如 NAT、防火墙、代理)可能主动断开连接。实现心跳检测的关键是:客户端和服务端**协同定时发送轻量 ping/pong 消息**,并设置超时判断连接是否存活。
客户端主动发心跳(ping)
在浏览器中,通常由客户端定时发送自定义的 ping 消息(比如 {"type":"ping"}),而不是依赖底层的 WebSocket 协议级 ping(浏览器不暴露该能力)。需注意避免在连接未就绪时发送。
- 使用
setInterval启动心跳定时器,间隔建议 20–30 秒(比服务端超时阈值略短) - 只在
ws.readyState === WebSocket.OPEN时发送,否则跳过或重试 - 消息体尽量小,例如 JSON 字符串
'{"t":"p"}'或纯字符串'ping' - 记录每次发送时间戳,用于后续超时判定
服务端响应 pong 并校验
服务端收到 ping 后应立即回复 pong(如 {"type":"pong"}),同时可更新该连接的最后活跃时间。更重要的是——服务端需主动检查连接是否“失联”。
- 为每个连接维护
lastPingTime,每次收到 ping 或业务消息时更新 - 用定时任务(如 Node.js 的
setInterval)扫描所有连接,若Date.now() - lastPingTime > timeoutThreshold(如 45s),则调用ws.close() - 收到客户端 pong 不需要额外处理,但可用来调试双向连通性
客户端监听超时与重连
仅发 ping 不够,客户端必须监控“发出 ping 后多久没收到 pong”,以此判断连接异常。
立即学习“Java免费学习笔记(深入)”;
- 每次发 ping 时启动一个
setTimeout,比如 10 秒后触发“心跳超时”逻辑 - 收到服务端 pong 时,清除对应定时器,并记录成功心跳
- 超时触发后,关闭当前 ws 实例,执行退避重连(如指数退避:1s → 2s → 4s…)
- 监听
onclose和onerror事件,统一纳入连接异常流程
利用原生 ping/pong(有限支持)
WebSocket 协议本身定义了控制帧 ping/pong,服务端可通过底层库(如 Node.js 的 ws 库)监听 ping 事件并自动回 pong。但浏览器端无法手动触发协议级 ping,ws.send() 发出的永远是文本/二进制数据帧。
- 服务端启用自动 pong 响应(
ws.ping()触发时自动回 pong)可简化逻辑 - 客户端仍需基于业务消息模拟心跳,不能依赖浏览器发送协议 ping
- 部分网关或负载均衡器会透传或响应协议 ping,但行为不统一,不可作为保活唯一依据


















