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);

浙公网安备 33010602011771号