网络切换导致websocket中断是常态,需以onclose/onerror为核心触发指数退避重连(500ms起,上限30s),配合应用层心跳(15–30秒ping/pong)和待发消息队列管理,避免丢失与重复。

网络从 4G 切换到 Wi-Fi 时,WebSocket 连接几乎必然中断——这不是异常,而是移动端的常态行为。系统重建网络栈、IP 地址变更、NAT 映射失效,都会导致底层 TCP 连接断开。JavaScript 本身无法阻止断连,但可以快速感知并重建连接。
主动监听断连信号
不要依赖“网络状态切换”事件(如 navigator.onLine),它滞后且不可靠。应以 WebSocket 自身状态为核心判断依据:
-
socket.onclose触发时,检查event.code和event.reason,若为非正常关闭(如 1006、1011)或未触发onopen就关闭,基本可判定是网络切换所致 -
socket.onerror通常伴随onclose,可作为辅助确认信号 - 避免仅靠
readyState === WebSocket.CLOSED判断,因为该值可能在连接尚未完全释放时就已更新
实现快速重连策略
重连不是简单地立即 new WebSocket(),需兼顾用户体验与服务端压力:
- 首次断连后延迟 500ms 重试,避免因瞬时抖动反复建链
- 连续失败时采用指数退避:500ms → 1s → 2s → 5s,上限建议设为 30s
- 设置最大重试次数(如 10 次),超限后暂停自动重连,交由用户手动触发或提示网络异常
- 重连前检查
navigator.onLine仅作参考,不阻断流程;真正决定是否重连的是 WebSocket 自身生命周期
配合心跳保活与验活机制
单纯靠浏览器原生心跳(pingInterval)不够,需应用层主动干预:
- 客户端每 15–30 秒发送一次自定义 ping 消息(如
{"type":"ping"}),服务端必须响应 pong - 若连续 2 次未收到 pong,主动调用
socket.close(),触发重连逻辑——这比等待 TCP 超时(往往数分钟)快得多 - 服务端也应定期检测客户端心跳,对无响应连接主动踢出,避免僵尸连接堆积
避免消息丢失的关键处理
断连期间产生的待发消息不能丢,也不能盲目重发:
- 维护一个内存队列(如
pendingMessages = []),所有send()前先检查readyState === WebSocket.OPEN,否则入队 - 重连成功且收到
onopen后,按顺序重发队列中消息;对时效敏感的消息(如打字状态),可加时间戳,超时(如 30s)则丢弃 - 服务端需支持消息去重(如通过 clientID + seqID),防止重连后重复投递
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











