当前位置: 首页 > news >正文

HOW - 保证 WebSocket 持续正常连接

一、基于 React 的 WebSocket

下面是一个React版本的WebSocket连接代码示例,展示了如何在React组件中实现WebSocket连接、心跳机制以及自动重连功能。

WebSocketManager.js

首先,我们可以创建一个 WebSocketManager 类来封装WebSocket的逻辑,包括连接、心跳和重连。

// WebSocketManager.jsclass WebSocketManager {constructor(url) {this.url = url;this.ws = null;// Ping和Pong是websocket里的心跳,用来保证客户端是在线的,一般来说只有服务端给客户端发送Ping,然后客户端发送Pong来回应,表明自己仍然在线this.pingInterval = null;this.pongTimeout = null;this.reconnectDelay = 5000; // 5秒后重新连接}connect() {this.ws = new WebSocket(this.url);this.ws.onopen = () => {console.log('Connected');this.startHeartbeat();};this.ws.onclose = (event) => {console.log(`Connection closed: ${event.reason}`);clearInterval(this.pingInterval);clearTimeout(this.pongTimeout);setTimeout(() => this.connect(), this.reconnectDelay);};this.ws.onerror = (error) => {console.error(`WebSocket error: ${error.message}`);};this.ws.onmessage = (event) => {const message = JSON.parse(event.data);if (message.type === 'pong') {console.log('Received pong');clearTimeout(this.pongTimeout);} else {this.handleMessage(message);}};}startHeartbeat() {this.pingInterval = setInterval(() => {if (this.ws.readyState === WebSocket.OPEN) {this.ws.send(JSON.stringify({ type: 'ping' }));this.pongTimeout = setTimeout(() => {console.warn('Pong timeout, closing connection');this.ws.close();}, 5000);}}, 30000);}handleMessage(message) {// 处理接收到的其他消息console.log('Received message:', message);}send(data) {if (this.ws.readyState === WebSocket.OPEN) {this.ws.send(JSON.stringify(data));}}
}export default WebSocketManager;

App.js

然后,在React组件中使用这个 WebSocketManager

// App.jsimport React, { useEffect } from 'react';
import WebSocketManager from './WebSocketManager';const App = () => {useEffect(() => {const wsManager = new WebSocketManager('ws://example.com/socket');wsManager.connect();// 清理函数,组件卸载时关闭 WebSocket 连接return () => {if (wsManager.ws) {clearInterval(wsManager.pingInterval);clearTimeout(wsManager.pongTimeout);wsManager.ws.close();}};}, []);return (<div className="App"><h1>WebSocket Demo</h1>{/* 其他组件或内容 */}</div>);
};export default App;

解释

  1. WebSocketManager 类

    • 封装 WebSocket 连接的逻辑,包含连接、心跳和重连功能。
    • connect 方法用于建立 WebSocket 连接并设置相应的事件处理器。
    • startHeartbeat 方法实现心跳机制,每隔30秒发送一次 ping 消息,如果5秒内没有收到 pong 响应,则关闭连接并触发重连。
    • handleMessage 方法处理接收到的其他消息,可以根据需要进行扩展。
    • send 方法用于发送消息。
  2. App 组件

    • 使用 useEffect 在组件挂载时创建 WebSocketManager 实例并建立连接,在组件卸载时清理定时器和关闭连接。

通过这种方式,可以在 React 项目中实现稳定的 WebSocket 连接,并具备自动重连和心跳检测功能。

注意:避免无限制重连

上面的示例中,客户端会一直尝试重连。每当连接关闭时,都会在5秒后重新尝试连接。这样可以确保在网络暂时中断或服务器暂时不可用的情况下,客户端能够自动恢复连接。

如果希望更精细地控制重连行为,例如限制重连次数或逐步增加重连间隔,可以进行以下改进:

  1. 限制重连次数

    • 可以增加一个变量来记录重连次数,并在超过最大重连次数后停止重连。
  2. 逐步增加重连间隔

    • 可以使用指数退避(exponential backoff)算法来逐步增加重连间隔,以避免频繁重连。

下面是改进后的 WebSocketManager 类:

// WebSocketManager.jsclass WebSocketManager {constructor(url) {this.url = url;this.ws = null;this.pingInterval = null;this.pongTimeout = null;this.reconnectDelay = 5000; // 初始重连延迟this.maxReconnectDelay = 30000; // 最大重连延迟this.reconnectAttempts = 0; // 重连次数this.maxReconnectAttempts = 10; // 最大重连次数}connect() {this.ws = new WebSocket(this.url);this.ws.onopen = () => {console.log('Connected');this.reconnectAttempts = 0; // 重置重连次数this.reconnectDelay = 5000; // 重置重连延迟this.startHeartbeat();};this.ws.onclose = (event) => {console.log(`Connection closed: ${event.reason}`);clearInterval(this.pingInterval);clearTimeout(this.pongTimeout);if (this.reconnectAttempts < this.maxReconnectAttempts) {this.reconnectAttempts++;setTimeout(() => this.connect(), this.reconnectDelay);this.reconnectDelay = Math.min(this.reconnectDelay * 2, this.maxReconnectDelay); // 指数退避} else {console.log('Max reconnect attempts reached. Giving up.');}};this.ws.onerror = (error) => {console.error(`WebSocket error: ${error.message}`);};this.ws.onmessage = (event) => {const message = JSON.parse(event.data);if (message.type === 'pong') {console.log('Received pong');clearTimeout(this.pongTimeout);} else {this.handleMessage(message);}};}startHeartbeat() {this.pingInterval = setInterval(() => {if (this.ws.readyState === WebSocket.OPEN) {this.ws.send(JSON.stringify({ type: 'ping' }));this.pongTimeout = setTimeout(() => {console.warn('Pong timeout, closing connection');this.ws.close();}, 5000);}}, 30000);}handleMessage(message) {// 处理接收到的其他消息console.log('Received message:', message);}send(data) {if (this.ws.readyState === WebSocket.OPEN) {this.ws.send(JSON.stringify(data));}}
}export default WebSocketManager;

解释:

  1. 限制重连次数

    • 增加了 reconnectAttemptsmaxReconnectAttempts 变量,用于记录和限制重连次数。
    • onclose 事件中,检查 reconnectAttempts 是否小于 maxReconnectAttempts,如果是则继续重连,否则停止重连。
  2. 逐步增加重连间隔

    • 使用 reconnectDelaymaxReconnectDelay 变量控制重连延迟。
    • 在每次重连后,使用 Math.min(this.reconnectDelay * 2, this.maxReconnectDelay) 增加重连延迟,直到达到最大重连延迟。

通过这种改进,可以更好地控制重连行为,避免客户端无限制地尝试重连,并在重连失败后逐步增加重连间隔。

当然,这个时间间隔应该最好可以比「服务端重启 Websocket」来的久,这样就可以在服务端出现故障重启时正常重连。

二、为什么会 ping 不通

当客户端一直无法 ping 通服务器时,可能会发生以下几种情况:

  1. 连接断开

    • 如果客户端无法接收到服务器的 pong 响应,可能意味着连接已经断开或存在网络问题。在这种情况下,客户端需要采取措施进行重连。
  2. 服务器无响应

    • 如果服务器因故未能回复 pong 消息,客户端会认为连接已失效。同样需要尝试重连。
  3. 连接超时

    • 为了防止无限等待,客户端可以设置一个超时时间。如果在指定时间内没有收到 pong 响应,就认为连接失效并进行重连。

三、保证持续正常连接的最佳实践

保证 WebSocket 持续正常连接可以通过以下几个步骤和最佳实践:

2.1 定时发送心跳消息 (Heartbeat/Ping-Pong)

定时发送心跳消息来保持连接活跃。服务器和客户端可以定期发送 Ping 和 Pong 消息,以确保连接未被中断。

const ws = new WebSocket('ws://example.com/socket');const interval = setInterval(() => {if (ws.readyState === WebSocket.OPEN) {ws.send(JSON.stringify({ type: 'ping' }));}
}, 30000); // 每30秒发送一次心跳消息ws.onmessage = (event) => {const message = JSON.parse(event.data);if (message.type === 'pong') {// 处理心跳回复}
};

2.2 自动重连机制

当连接断开时,自动尝试重新连接。

let ws;function connect() {ws = new WebSocket('ws://example.com/socket');ws.onopen = () => {console.log('Connected');};ws.onclose = (event) => {console.log(`Connection closed: ${event.reason}`);setTimeout(connect, 5000); // 5秒后重新连接};ws.onerror = (error) => {console.error(`WebSocket error: ${error.message}`);};ws.onmessage = (event) => {// 处理接收到的消息};
}connect();

2.3 检测网络状态

通过监听网络状态变化来处理网络断开和恢复。

window.addEventListener('online', () => {console.log('Network is online. Attempting to reconnect...');connect();
});window.addEventListener('offline', () => {console.log('Network is offline. Closing WebSocket connection...');ws.close();
});

2.4 处理服务器端断开

服务器端可以通过发送特定消息通知客户端即将断开,客户端收到后可进行相应处理。

ws.onmessage = (event) => {const message = JSON.parse(event.data);if (message.type === 'server-close') {console.log('Server is closing the connection');ws.close();}
};

2.5 增加异常处理

在连接的生命周期内,添加对各种异常情况的处理,以确保程序不会因为未处理的异常而崩溃。

ws.onerror = (error) => {console.error(`WebSocket error: ${error.message}`);// 可以根据错误类型进行不同的处理,例如重连、提示用户等
};

通过上述方法,可以提高 WebSocket 连接的稳定性和持续性,确保在网络状况良好时,连接可以保持正常。如果遇到网络波动或其他异常情况,也能及时进行恢复和重连。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • [解决方法]Request failed with status code 500错误之一
  • AI测试入门(1):认识AI大语言模型(LLM)
  • nodejs安装+踩坑报错解决
  • django报错(二):NotSupportedError:MySQL 8 or later is required (found 5.7.43)
  • Python 基础——列表(list)
  • Xcode如何创建多个工程
  • 提高Java程序效率:ImmutableList、Stream API 和 JSON序列化实战指南
  • 【保姆级】Python项目部署到Linux生产环境(uwsgi+python+flask+nginx服务器)
  • python编程技巧——list计算
  • 继承与多态 Java
  • macOS 环境Qt Creator 快捷键
  • SimMIM:一个类BERT的计算机视觉的预训练框架
  • vue学习笔记(十)——Vuex(状态管理,组件间共享数据)
  • 极狐GitLab 如何管理 PostgreSQL 扩展?
  • 系统架构设计师教程(清华第二版) 第3章 信息系统基础知识-3.2 业务处理系统-解读
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • angular组件开发
  • avalon2.2的VM生成过程
  • egg(89)--egg之redis的发布和订阅
  • Git学习与使用心得(1)—— 初始化
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • Java多态
  • js ES6 求数组的交集,并集,还有差集
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • Rancher-k8s加速安装文档
  • SOFAMosn配置模型
  • 安卓应用性能调试和优化经验分享
  • 浅谈web中前端模板引擎的使用
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 入门到放弃node系列之Hello Word篇
  • 山寨一个 Promise
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 说说我为什么看好Spring Cloud Alibaba
  • # wps必须要登录激活才能使用吗?
  • $NOIp2018$劝退记
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (003)SlickEdit Unity的补全
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (STM32笔记)九、RCC时钟树与时钟 第一部分
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (回溯) LeetCode 46. 全排列
  • (四)c52学习之旅-流水LED灯
  • (四十一)大数据实战——spark的yarn模式生产环境部署
  • (转)Linq学习笔记
  • (转)大型网站的系统架构
  • (转)拼包函数及网络封包的异常处理(含代码)
  • ***原理与防范
  • .env.development、.env.production、.env.staging
  • .JPG图片,各种压缩率下的文件尺寸
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost