WebSocket
WebSocket 是一种基于 TCP 的全双工通信协议,允许服务端主动向客户端推送数据。
与 HTTP 协议的区别
- 连接方式:HTTP 是短连接(无状态),WebSocket 是长连接。
- 通信模式:HTTP 只能客户端发起请求,WebSocket 支持双向实时通信。
- 协议头:WebSocket 通过
ws://或wss://(加密)建立连接,握手阶段使用 HTTP 协议(状态码 101)。
WebSocket 的优点 / 缺点
优点
- 双向通信:WebSocket 提供了全双工通信机制,服务器和客户端可以在任何时刻发送数据给对方,适合需要实时数据交换的应用,如在线游戏、实时聊天等。
- 更低的延迟:一旦 WebSocket 连接建立,数据可以快速地在客户端和服务器之间传输,减少了 HTTP 每次请求都需要建立连接的开销。
- 减少通信量:WebSocket 在建立连接后,数据交换不需要每次都包含 HTTP 的头部信息,减少了额外的网络负载。
- 保持连接状态:WebSocket 通过一个持久的连接,可以更容易地管理和保持客户端和服务器之间的状态。
缺点
- 兼容性和支持:虽然现代浏览器都支持 WebSocket,但在一些旧的浏览器或网络设备中可能不被支持。
- 安全性:WebSocket 可能会增加安全风险,因为它保持了一个持久的连接。需要实现额外的安全措施,如使用
WSS(WebSocket Secure 即 WebSocket 协议的加密版本)。 - 复杂性:相对于简单的 HTTP 请求/响应模型,WebSocket 的实现和调试可能更复杂,特别是在处理大规模、高并发的连接时。
- 服务器资源:WebSocket 连接是持久的,相比于 HTTP 的无状态连接,它可能会占用更多的服务器资源。
心跳检测
定时发送 ping/pong 帧检测连接活性。
setInterval(() => {
if (socket.readyState === WebSocket.OPEN) {
socket.send('ping');
}
}, 30000);如果心跳检测不正常,那么尝试重新发起 WebSocket 连接(超过一定次数后提示用户手动刷新网页之类的操作重连)。
WebSocket 握手过程
- 客户端发送 HTTP 请求,包含 Upgrade: websocket 和 Sec-WebSocket-Key。
- 服务器返回状态码 101,包含 Sec-WebSocket-Accept(由客户端 Key 计算生成)。
WebSocket 性能优化
- 数据压缩(如使用
permessage-deflate扩展)。 - 分片传输大数据,避免阻塞。
- 合理设计消息格式(如 JSON 或二进制协议)。
实现一个带重连机制的 WebSocket 客户端
class AutoReconnectWebSocket {
constructor(url) {
this.url = url;
this.socket = null;
this.reconnectInterval = 1000;
this.connect();
}
connect() {
this.socket = new WebSocket(this.url);
this.socket.onopen = () => {
console.log('Connected');
this.reconnectInterval = 1000; // 重置重连间隔
};
this.socket.onclose = (e) => {
console.log(`断开连接,${e.reason}`);
setTimeout(() => this.connect(), this.reconnectInterval);
this.reconnectInterval *= 2; // 指数退避
};
this.socket.onerror = (err) => {
console.error('WebSocket 错误:', err);
this.socket.close();
};
}
send(data) {
if (this.socket.readyState === WebSocket.OPEN) {
this.socket.send(data);
}
}
}