WebSocket 维持连接的核心机制主要依赖于以下几个关键技术点:
### 1. 握手协议建立连接
WebSocket 通过 HTTP 升级协议建立初始连接:
```javascript
// 客户端发起WebSocket连接
const socket = new WebSocket('ws://example.com/socket');
// 服务端响应(Node.js示例)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
console.log('连接已建立');
});
握手过程包含:
- 客户端发送
Upgrade: websocket头 - 服务端响应
101 Switching Protocols - 交换
Sec-WebSocket-Key验证
2. 心跳机制保持活跃
两种常见的心跳实现方式:
方案A:Ping/Pong帧
// 服务端定时发送Ping
setInterval(() => {
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.ping();
}
});
}, 30000);
// 客户端响应Pong
socket.on('pong', () => {
console.log('收到心跳响应');
});
方案B:自定义心跳协议
// 双向心跳检测
let heartbeatInterval;
socket.on('open', () => {
heartbeatInterval = setInterval(() => {
socket.send(JSON.stringify({ type: 'heartbeat' }));
}, 25000);
});
socket.on('message', (data) => {
if (data.type === 'heartbeat') {
socket.send(JSON.stringify({ type: 'heartbeat_ack' }));
}
});
3. 断线重连策略
健壮的重连实现示例:
let reconnectAttempts = 0;
const maxReconnectAttempts = 5;
function connect() {
const socket = new WebSocket('ws://example.com/socket');
socket.onclose = (e) => {
if (reconnectAttempts < maxReconnectAttempts) {
const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30000);
setTimeout(connect, delay);
reconnectAttempts++;
}
};
socket.onopen = () => {
reconnectAttempts = 0;
};
}
4. 流量控制优化
关键优化手段:
- 使用二进制帧替代文本传输
// 发送ArrayBuffer
const buffer = new ArrayBuffer(128);
socket.send(buffer);
// 接收二进制数据
socket.binaryType = 'arraybuffer';
socket.onmessage = (e) => {
if (e.data instanceof ArrayBuffer) {
// 处理二进制数据
}
};
5. 连接状态监控
完整的连接状态管理:
const connectionMonitor = {
lastActivity: Date.now(),
start() {
setInterval(() => {
if (Date.now() - this.lastActivity > 60000) {
socket.close();
}
}, 10000);
},
recordActivity() {
this.lastActivity = Date.now();
}
};
socket.onmessage = () => connectionMonitor.recordActivity();
最佳实践总结
- 始终实现双向心跳检测
- 采用指数退避重连策略
- 重要操作添加消息确认机制
- 生产环境建议使用WSS协议
- 考虑使用Socket.io等成熟库处理兼容性问题
完整实现示例:
class RobustWebSocket {
constructor(url) {
this.url = url;
this.reconnectDelay = 1000;
this.maxReconnectDelay = 30000;
this.connect();
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
this.startHeartbeat();
this.reconnectDelay = 1000;
};
this.ws.onclose = () => {
setTimeout(() => this.connect(),
Math.min(this.reconnectDelay *= 2, this.maxReconnectDelay));
};
}
startHeartbeat() {
clearInterval(this.heartbeatInterval);
this.heartbeatInterval = setInterval(() => {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send('ping');
}
}, 25000);
}
}