news 2026/4/18 6:31:12

websocket的异常处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
websocket的异常处理

WebSocket 异常处理需要从连接、通信、断开等各个环节进行全面的错误管理。以下是详细的处理方案:

一、连接阶段异常处理

1. 连接建立失败

const socket = new WebSocket('ws://example.com'); // 连接错误 socket.onerror = (error) => { console.error('WebSocket连接错误:', error); // 执行重连逻辑 reconnect(); }; // 连接超时处理 const connectTimeout = setTimeout(() => { if (socket.readyState !== WebSocket.OPEN) { socket.close(); console.error('连接超时'); } }, 5000); socket.onopen = () => { clearTimeout(connectTimeout); console.log('连接成功'); };

2. 重连机制

class WebSocketManager { constructor(url, options = {}) { this.url = url; this.maxRetries = options.maxRetries || 5; this.retryCount = 0; this.reconnectDelay = options.reconnectDelay || 1000; this.socket = null; } connect() { this.socket = new WebSocket(this.url); this.socket.onopen = () => { console.log('WebSocket连接成功'); this.retryCount = 0; // 重置重试计数 }; this.socket.onerror = (error) => { console.error('WebSocket错误:', error); }; this.socket.onclose = (event) => { console.log(`连接关闭,代码: ${event.code}, 原因: ${event.reason}`); if (this.shouldReconnect(event)) { this.scheduleReconnect(); } }; } shouldReconnect(closeEvent) { // 非正常关闭且未超过最大重试次数 return closeEvent.code !== 1000 && this.retryCount < this.maxRetries; } scheduleReconnect() { this.retryCount++; const delay = this.reconnectDelay * Math.pow(2, this.retryCount - 1); console.log(`${delay/1000}秒后尝试第${this.retryCount}次重连`); setTimeout(() => { this.connect(); }, delay); } }

二、通信阶段异常处理

1. 发送消息异常

class WebSocketService { sendMessage(message) { if (this.socket.readyState === WebSocket.OPEN) { try { // 序列化消息 const data = typeof message === 'object' ? JSON.stringify(message) : message; this.socket.send(data); return true; } catch (error) { console.error('发送消息失败:', error); this.queueMessage(message); // 进入消息队列 return false; } } else { console.warn('WebSocket未连接,消息被缓存'); this.queueMessage(message); return false; } } queueMessage(message) { // 实现消息队列 this.messageQueue.push(message); } // 连接恢复后发送队列中的消息 flushMessageQueue() { while (this.messageQueue.length > 0 && this.socket.readyState === WebSocket.OPEN) { const message = this.messageQueue.shift(); this.sendMessage(message); } } }

2. 接收消息异常

socket.onmessage = (event) => { try { let data; // 处理不同类型的数据 if (typeof event.data === 'string') { data = JSON.parse(event.data); } else if (event.data instanceof Blob) { // 处理二进制数据 this.handleBlobData(event.data); return; } else if (event.data instanceof ArrayBuffer) { // 处理ArrayBuffer this.handleArrayBuffer(event.data); return; } // 处理数据 this.processMessage(data); } catch (error) { console.error('处理消息失败:', error); // 发送错误确认 this.sendErrorAck(error.message); // 记录错误日志 this.logError({ type: 'MESSAGE_PARSE_ERROR', error: error.message, rawData: event.data }); } };

三、心跳机制与超时处理

1. 心跳检测

class HeartbeatManager { constructor(socket, interval = 30000) { this.socket = socket; this.interval = interval; this.pingInterval = null; this.pongTimeout = null; this.lastPongTime = null; } start() { this.pingInterval = setInterval(() => { if (this.socket.readyState === WebSocket.OPEN) { this.sendPing(); this.waitForPong(); } }, this.interval); } sendPing() { try { this.socket.send(JSON.stringify({ type: 'ping', timestamp: Date.now() })); } catch (error) { console.error('发送心跳失败:', error); } } waitForPong() { // 设置pong超时 this.pongTimeout = setTimeout(() => { console.error('心跳响应超时'); this.socket.close(4000, 'Heartbeat timeout'); }, 5000); } handlePong() { clearTimeout(this.pongTimeout); this.lastPongTime = Date.now(); } stop() { clearInterval(this.pingInterval); clearTimeout(this.pongTimeout); } }

四、完整封装示例

class RobustWebSocket { constructor(url, options = {}) { this.url = url; this.options = { maxRetries: 5, reconnectDelay: 1000, heartbeatInterval: 30000, ...options }; this.socket = null; this.retryCount = 0; this.messageQueue = []; this.heartbeat = null; this.eventHandlers = new Map(); this.connect(); } connect() { try { this.socket = new WebSocket(this.url); this.setupEventListeners(); } catch (error) { console.error('创建WebSocket失败:', error); this.handleConnectionError(error); } } setupEventListeners() { this.socket.onopen = this.handleOpen.bind(this); this.socket.onmessage = this.handleMessage.bind(this); this.socket.onerror = this.handleError.bind(this); this.socket.onclose = this.handleClose.bind(this); } handleOpen() { console.log('WebSocket连接成功'); this.retryCount = 0; // 启动心跳 this.startHeartbeat(); // 发送队列中的消息 this.flushMessageQueue(); // 触发事件 this.emit('connected'); } handleMessage(event) { try { const message = this.parseMessage(event.data); // 处理心跳响应 if (message.type === 'pong') { this.heartbeat?.handlePong(); return; } // 触发消息事件 this.emit('message', message); } catch (error) { console.error('消息处理错误:', error); this.emit('error', { type: 'MESSAGE_ERROR', error: error.message }); } } handleError(error) { console.error('WebSocket错误:', error); this.emit('error', { type: 'WEBSOCKET_ERROR', error: error }); } handleClose(event) { console.log(`连接关闭,代码: ${event.code}, 原因: ${event.reason}`); // 停止心跳 this.stopHeartbeat(); // 触发断开事件 this.emit('disconnected', { code: event.code, reason: event.reason }); // 判断是否需要重连 if (this.shouldReconnect(event)) { this.scheduleReconnect(); } } shouldReconnect(closeEvent) { // 1000-1004 是正常关闭代码,不重连 const normalCloseCodes = [1000, 1001, 1005]; return !normalCloseCodes.includes(closeEvent.code) && this.retryCount < this.options.maxRetries; } send(data) { return new Promise((resolve, reject) => { if (this.socket?.readyState === WebSocket.OPEN) { try { const message = typeof data === 'object' ? JSON.stringify(data) : data; this.socket.send(message); resolve(); } catch (error) { console.error('发送失败:', error); this.queueMessage(data); reject(error); } } else { console.warn('连接未就绪,消息进入队列'); this.queueMessage(data); reject(new Error('WebSocket not connected')); } }); } close(code = 1000, reason = 'Normal closure') { this.stopHeartbeat(); this.socket?.close(code, reason); } // 事件系统 on(event, handler) { if (!this.eventHandlers.has(event)) { this.eventHandlers.set(event, []); } this.eventHandlers.get(event).push(handler); } emit(event, data) { const handlers = this.eventHandlers.get(event) || []; handlers.forEach(handler => handler(data)); } // 其他辅助方法... } // 使用示例 const ws = new RobustWebSocket('ws://example.com', { maxRetries: 3, reconnectDelay: 2000 }); ws.on('connected', () => { console.log('已连接'); }); ws.on('message', (data) => { console.log('收到消息:', data); }); ws.on('error', (error) => { console.error('发生错误:', error); }); ws.on('disconnected', (reason) => { console.log('断开连接:', reason); });

五、服务器端异常处理(Node.js示例)

const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', (ws, req) => { console.log('客户端连接'); // 设置消息处理 ws.on('message', (message) => { try { // 验证消息格式 if (this.isValidMessage(message)) { // 处理消息 this.handleMessage(ws, message); } else { throw new Error('Invalid message format'); } } catch (error) { console.error('处理客户端消息错误:', error); // 发送错误响应 ws.send(JSON.stringify({ type: 'error', error: error.message })); } }); // 错误处理 ws.on('error', (error) => { console.error('WebSocket错误:', error); }); // 连接关闭 ws.on('close', (code, reason) => { console.log(`客户端断开,代码: ${code}, 原因: ${reason}`); // 清理资源 this.cleanupClientResources(ws); }); // 设置心跳 const heartbeatInterval = setInterval(() => { if (ws.readyState === WebSocket.OPEN) { ws.ping(); } }, 30000); ws.on('pong', () => { // 更新最后活动时间 ws.isAlive = true; }); // 清理定时器 ws.on('close', () => { clearInterval(heartbeatInterval); }); });

六、最佳实践总结

  1. 分级处理错误:区分连接错误、通信错误、业务错误

  2. 优雅降级:WebSocket失败时降级到轮询或SSE

  3. 监控告警:记录关键指标,设置阈值告警

  4. 资源清理:确保连接关闭时释放所有资源

  5. 安全考虑:验证消息来源,防止注入攻击

  6. 性能优化:合理设置缓冲区,避免内存泄漏

  7. 兼容性处理:考虑不同浏览器的实现差异

通过以上全面的异常处理机制,可以构建健壮的WebSocket应用,提供稳定的实时通信能力。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 3:48:14

删除当前视频按钮图标[特殊字符]️含义说明及操作确认

删除当前视频按钮图标&#x1f5d1;️含义说明及操作确认 在如今的AI内容生成系统中&#xff0c;用户面对的不再是单次任务的简单输出&#xff0c;而是成百上千条视频记录的持续积累。以HeyGem数字人视频生成系统为例&#xff0c;每一次语音驱动、表情合成都会产生一个独立的视…

作者头像 李华
网站建设 2026/4/18 5:07:38

基于YOLOv10的杂草检测系统(12种)(YOLOv10深度学习+YOLO数据集+UI界面+Python项目源码+模型)

一、项目介绍 摘要 本项目基于YOLOv10目标检测算法开发了一套高效的杂草识别系统&#xff0c;专门用于检测和分类12种常见杂草物种。系统通过深度学习技术实现了对农田杂草的精准识别&#xff0c;为精准农业和智能除草提供了技术支持。项目使用包含3319张标注图像的数据集&am…

作者头像 李华
网站建设 2026/4/18 5:13:04

PHP 8.7引入了哪些隐藏函数?99%开发者还没发现的秘密

第一章&#xff1a;PHP 8.7引入的新函数概述PHP 8.7 作为 PHP 语言持续演进的重要版本&#xff0c;引入了一系列实用且高效的新内置函数&#xff0c;旨在提升开发效率、增强类型安全并简化常见编程任务。这些函数覆盖了字符串处理、数组操作、类型判断以及异步支持等多个方面&a…

作者头像 李华
网站建设 2026/4/17 22:21:40

PHP插件开发新纪元:如何在低代码浪潮中打造不可替代的技术壁垒

第一章&#xff1a;PHP插件开发新纪元&#xff1a;低代码浪潮下的技术突围在数字化转型加速的背景下&#xff0c;PHP插件开发正迎来一场由低代码平台驱动的技术变革。传统开发模式中&#xff0c;开发者需手动编写大量重复代码以实现基础功能&#xff0c;而如今&#xff0c;低代…

作者头像 李华
网站建设 2026/4/18 3:13:39

【PHP与工业通信协议深度整合】:实现秒级数据上传的终极方案

第一章&#xff1a;PHP与工业通信协议融合的背景与意义 随着工业自动化与信息化深度融合&#xff0c;传统工业控制系统正逐步向智能化、网络化方向演进。在这一背景下&#xff0c;将广泛应用于Web开发的PHP语言引入工业通信领域&#xff0c;成为连接企业资源计划&#xff08;ER…

作者头像 李华
网站建设 2026/4/18 5:07:38

PHP温控系统部署避坑指南(5大常见故障与修复方案)

第一章&#xff1a;PHP智能家居温度控制概述在现代物联网&#xff08;IoT&#xff09;应用中&#xff0c;智能家居系统逐渐成为家庭自动化的重要组成部分。其中&#xff0c;温度控制作为核心功能之一&#xff0c;直接影响居住舒适度与能源效率。PHP 作为一种广泛使用的服务器端…

作者头像 李华