WebSocket断线重连后消息重复发送怎么办?
在做在线协作编辑器时用WebSocket同步数据,但发现客户端断线重连后,之前发送的半条消息会和重连后的新消息拼在一起。比如输入”hello”时断线,重连后继续输入” world”,服务端收到的是”hello worldhello”。试过在重连时清空本地缓存队列,但用户刚恢复输入时又会出现重复。控制台显示连接状态是”open”,但消息体里带上了上次未完成的草稿内容。
以下是消息容器的样式代码,可能和状态显示有关:
.message-container {
position: relative;
max-height: 200px;
overflow-y: auto;
}
.message {
display: flex;
align-items: center;
padding: 8px;
margin: 4px 0;
border-radius: 4px;
}
.message.error {
background-color: #fee;
border-left: 4px solid #f00;
}
检查过连接状态判断逻辑,发现reconnect时虽然关闭了旧连接,但消息发送函数可能在断线期间被多次调用了。有没有标准的重连时消息重发策略,既能保证消息可靠又不重复?
实在懒得改的话,就让后端去重,简单粗暴但有效。
在客户端维护一个待发送的消息队列,每次发送前检查 WebSocket 状态:
重连时清空旧连接的回调事件,避免重复触发:
消息体需要添加唯一ID,服务端进行幂等校验:
具体原理是:
通过切断旧连接所有事件回调,避免重连期间收到历史消息
用独立队列管理待发消息,而不是依赖浏览器缓存
消息ID确保即使重复发送服务端也能识别
轮询检测连接状态比单纯监听onopen更可靠,因为onopen触发后连接可能还没完全就绪
这样处理后消息丢失和重复的概率基本为0了。建议同时在服务端做消息去重,形成双重保险。