websocket封装
WebSocket 是一种基于 TCP 的通信协议,允许客户端与服务器之间建立一个持久的连接,进行双向实时通信。
1. WebSocket 构造函数
通过 new WebSocket(url)
创建 WebSocket 实例。
const ws = new WebSocket('ws://your-websocket-url');
2. WebSocket 主要方法
send(data)
用于向服务器发送数据。可以发送文本数据或二进制数据(如 Blob 或 ArrayBuffer)。注意:只有在连接成功后,readyState
为 OPEN
时才能发送数据。
ws.send('Hello, Server!');
close(code?, reason?)
用于关闭 WebSocket 连接。code
和 reason
是可选参数:
code
(可选):指定 WebSocket 连接关闭的状态码,默认是1000
,表示正常关闭。reason
(可选):指定一个关闭的原因,最大长度为 123 字符。
ws.close(1000, 'Normal closure');
3. WebSocket 主要属性
readyState
WebSocket 的状态,返回一个数字,表示连接的当前状态。它有 4 个可能的值:
0
:CONNECTING
- WebSocket 连接正在建立。1
:OPEN
- WebSocket 连接已建立,可以进行通信。2
:CLOSING
- WebSocket 正在关闭。3
:CLOSED
- WebSocket 连接已经关闭或无法打开。
可以通过 ws.readyState
来查看当前 WebSocket 的状态。
bufferedAmount
返回当前 WebSocket 发送队列中的字节数。这可以帮助你了解缓冲区中还有多少数据等待发送。
4. WebSocket 事件
WebSocket 通过以下事件与客户端进行交互:
onopen:
当 WebSocket 连接成功建立时触发。可以在这里初始化与服务器的交互。
ws.onopen = function(event) { console.log('WebSocket is open now.'); };
onmessage:
当 WebSocket 接收到消息时触发。该事件处理程序的 event
对象的 data
属性包含了接收到的数据(字符串或二进制数据)。
ws.onmessage = function(event) { console.log('Received data: ', event.data); };
onerror:
当 WebSocket 发生错误时触发。通常会在 WebSocket 连接发生故障或无法建立连接时触发。
ws.onerror = function(event) { console.error('WebSocket error:', event); };
onclose:
当 WebSocket 连接关闭时触发。你可以在这里执行一些清理操作。
ws.onclose = function(event) { console.log('WebSocket closed', event.code, event.reason); };
5. 带心跳检测和自动重连的websocket封装库
为了确保 WebSocket 连接保持活跃,可以定期发送“心跳”消息。如果服务器在一定时间内没有回应,可以视为连接断开,触发重连。
核心实现:
- 客户端定期发送心跳请求(ping)。
- 服务器收到心跳请求后返回响应(pong)。
- 客户端在规定时间内未收到服务器的
pong
响应时,触发重连机制。
使用 setInterval
来定时发送心跳消息。例如,每隔 30 秒向服务器发送一个“ping”消息。
当客户端收到服务器返回的 pong
消息时,清除现有的定时器并重新启动,以保证心跳机制持续有效。
class WebSocketWithHeartbeatAndReconnect { constructor(url, options = {}) { this.url = url; this.socket = null; this.heartbeatInterval = options.heartbeatInterval || 30000; // 默认每 30 秒发送一次心跳 this.pingMessage = options.pingMessage || 'ping'; // 默认 ping 消息 this.pongMessage = options.pongMessage || 'pong'; // 默认 pong 消息 this.reconnectInterval = options.reconnectInterval || 5000; // 默认每 5 秒尝试重连 this.maxReconnectAttempts = options.maxReconnectAttempts || 5; // 最大重连次数 this.reconnectAttempts = 0; // 当前已尝试的重连次数 this.heartbeatTimer = null; // 存储心跳定时器 this.reconnectTimer = null; // 存储重连定时器 } // 初始化 WebSocket 连接 connect() { if (this.socket) { this.socket.close(); // 关闭现有连接 } this.socket = new WebSocket(this.url); // 连接成功时启动心跳 this.socket.onopen = () => { console.log('WebSocket connected'); this.reconnectAttempts = 0; // 重置重连次数 this.startHeartbeat(); // 启动心跳机制 }; // 接收到消息时 this.socket.onmessage = (event) => { console.log('Received message:', event.data); // 如果接收到 pong 消息,说明服务器回应了心跳 if (event.data === this.pongMessage) { console.log('Pong received'); this.resetHeartbeat(); // 重置心跳定时器 } }; // 连接关闭时 this.socket.onclose = (event) => { console.log('WebSocket closed:', event); this.stopHeartbeat(); // 停止心跳机制 this.handleReconnect(); // 尝试重连 }; // 错误处理 this.socket.onerror = (error) => { console.error('WebSocket error:', error); this.socket.close(); // 在发生错误时关闭连接 }; } // 启动心跳机制,定时发送 ping 消息 startHeartbeat() { this.heartbeatTimer = setInterval(() => { if (this.socket && this.socket.readyState === WebSocket.OPEN) { console.log('Sending ping...'); this.socket.send(this.pingMessage); // 发送 ping 消息 } }, this.heartbeatInterval); } // 重置心跳机制 resetHeartbeat() { clearInterval(this.heartbeatTimer); // 清除之前的心跳定时器 this.startHeartbeat(); // 重新启动心跳定时器 } // 停止心跳机制 stopHeartbeat() { clearInterval(this.heartbeatTimer); // 清除心跳定时器 } // 处理重连机制 handleReconnect() { if (this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnectAttempts++; console.log(`Attempting to reconnect... (${this.reconnectAttempts}/${this.maxReconnectAttempts})`); // 重连时延 this.reconnectTimer = setTimeout(() => { this.connect(); // 尝试重新连接 }, this.reconnectInterval); } else { console.log('Max reconnect attempts reached. Giving up.'); } } // 发送数据 send(message) { if (this.socket && this.socket.readyState === WebSocket.OPEN) { this.socket.send(message); console.log('Message sent:', message); } else { console.log('WebSocket is not open. Cannot send message.'); } } // 关闭连接 close() { if (this.socket) { this.socket.close(); console.log('WebSocket closed manually.'); } } } // 使用示例 const wsClient = new WebSocketWithHeartbeatAndReconnect('ws://your-websocket-url', { heartbeatInterval: 30000, // 每 30 秒发送心跳 reconnectInterval: 5000, // 每 5 秒尝试重连 maxReconnectAttempts: 10, // 最大尝试 10 次 }); // 启动 WebSocket 连接 wsClient.connect(); // 发送数据 setTimeout(() => { wsClient.send('Hello WebSocket'); }, 5000); // 关闭连接 setTimeout(() => { wsClient.close(); }, 20000);