# WebSocket
WebSocket 是一种基于 TCP 的全双工通信协议,它的核心作用是打破 HTTP 协议 “请求 - 响应” 的单向通信限制,让客户端和服务端建立连接后,能双向、实时地收发数据。
它的工作流程分两步:
- 握手阶段:依赖 HTTP 完成。客户端发送一个带
Upgrade: websocket字段的 HTTP 请求,服务端返回 101 状态码,协议就从 HTTP 升级为 WebSocket,建立持久连接。- 通信阶段:连接建立后,双方不需要每次请求都带冗余的 HTTP 头,直接以 “帧” 的形式传输数据,延迟极低。
对比 HTTP 的话,HTTP 是 “客户端问、服务端答”,服务端不能主动发消息;而 WebSocket 是 “电话接通后,双方随时能说话”,特别适合实时聊天、股票行情、在线游戏这类场景。
# 补充:WebSocket 核心优势(面试加分点)
- 全双工:同一连接上,客户端和服务端可同时发数据,不像 HTTP 同一时刻只能单向传输。
- 长连接低开销:一次握手,持久连接,避免 HTTP 短连接频繁创建 / 销毁 TCP 连接的性能损耗。
- 轻量级:数据帧头很小,比 HTTP 请求头节省带宽。
# 二、 如何解释 WebSocket 重连机制(实战重点,面试官超关心)
面试官大概率会追问 “WebSocket 连接断了怎么办?”,这时候要讲重连的必要性 + 核心思路 + 具体实现方案,结合代码思路更佳:
WebSocket 连接很容易因为网络波动、服务端重启、客户端休眠(比如浏览器切后台)而断开,所以必须实现自动重连机制,保证通信的可靠性。
重连的核心思路是:监听连接关闭 / 错误事件 → 延迟重试 → 避免频繁重试 → 重连成功后恢复业务逻辑。
# 1. 重连机制的核心实现步骤(分 4 步,带伪代码思路)
# (1)监听断开事件,触发重连
WebSocket 有 onclose 和 onerror 两个事件,只要触发,就说明连接断了,需要启动重连。
javascript
运行
let ws = null;
// 初始化连接方法
function initWebSocket() {
ws = new WebSocket('wss://xxx.com/chat');
// 连接成功
ws.onopen = () => {
console.log('连接成功');
// 重连成功后,可发送心跳或恢复订阅
sendHeartbeat();
};
// 接收消息
ws.onmessage = (e) => {
console.log('收到消息', e.data);
};
// 连接关闭/错误,触发重连
ws.onclose = (e) => {
console.log('连接关闭,准备重连');
reconnect();
};
ws.onerror = (e) => {
console.log('连接错误,准备重连');
reconnect();
};
}
# (2)延迟重试 + 指数退避(避免频繁请求压垮服务端)
核心原则:不能连接一断就立刻重试(比如网络彻底断了,重试也是白耗资源),要加延迟,并且失败次数越多,延迟越长(指数退避策略),同时设置最大重试次数,防止无限重试。
javascript
运行
let retryCount = 0; // 重试次数
const MAX_RETRY = 10; // 最大重试次数
const BASE_DELAY = 1000; // 基础延迟时间(1秒)
function reconnect() {
// 超过最大重试次数,停止重连,提示用户
if (retryCount >= MAX_RETRY) {
alert('网络异常,无法重连,请刷新页面');
return;
}
// 指数退避:延迟时间 = 基础延迟 * 2^重试次数
const delay = BASE_DELAY * Math.pow(2, retryCount);
retryCount++;
// 延迟后重新初始化连接
setTimeout(() => {
console.log(`第${retryCount}次重连,延迟${delay}ms`);
initWebSocket();
}, delay);
}
# (3)心跳机制(预防 “假死” 连接)
很多时候,连接物理没断,但已经失效(比如防火墙超时断开),这种情况 onclose 不会触发,需要用心跳包检测连接状态。
心跳机制:客户端定期给服务端发一个 “心跳消息”,服务端收到后回复 “心跳响应”。如果客户端多次发心跳都没收到响应,就主动断开并触发重连。
javascript
运行
let heartbeatTimer = null;
// 发送心跳
function sendHeartbeat() {
// 定时发送心跳(比如每10秒发一次)
heartbeatTimer = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send('ping'); // 心跳消息,格式自定义
} else {
// 连接状态不对,清除定时器
clearInterval(heartbeatTimer);
}
}, 10000);
}
// 服务端返回pong,说明连接正常
ws.onmessage = (e) => {
if (e.data === 'pong') {
console.log('心跳正常');
// 收到响应,重置重试次数(如果之前有失败)
retryCount = 0;
} else {
// 处理业务消息
}
};
# (4)重连成功后恢复业务
重连成功后,需要恢复之前的业务状态,比如:
- 重新发送之前未成功发送的消息;
- 重新订阅用户关注的频道(比如聊天房间);
- 清空重试次数,重置心跳定时器。
# 三、 面试总结话术(一句话收尾)
总的来说,WebSocket 解决了 HTTP 实时通信的痛点,而重连机制是保证 WebSocket 稳定性的关键,核心是监听断开事件 + 指数退避重试 + 心跳检测 + 业务恢复,这样就能在复杂的网络环境下,保证实时通信的可靠性。
上一篇: 下一篇: