使WebSocket 稳定可靠,需要考虑的方向
文章目录
- 1. 连接管理
- 2. 心跳检测
- 3. 重连机制
- 4. 消息队列
- 5. 错误处理
- 6. 资源管理
- 7. 安全性
- 8. 状态同步
- 示例代码
- 1. 添加依赖
- 2. WebSocket 客户端实现
- 代码注释
- 功能标注
- 3. 安卓端使用
- MainActivity.java
- 布局文件(`activity_main.xml`)
- 4. 后端(Flask + Flask-SocketIO)
- 安装依赖
- Flask 应用代码(`app.py`)
- 5. 运行
在基于 WebSocket 开发应用时,为了保证连接的良好状态并提供稳定的实时通信,通常需要实现以下功能:
1. 连接管理
- 建立连接:初始化 WebSocket 连接。
- 保持连接状态:监控连接状态,确保连接始终处于活跃状态。
- 关闭连接:在合适的时候(如用户退出、应用销毁等)正确关闭连接,释放资源。
2. 心跳检测
- 发送心跳消息:定期向服务器发送心跳消息(如
"ping"),以检测连接是否仍然活跃。 - 接收心跳响应:服务器收到心跳消息后,返回响应(如
"pong")。客户端通过接收响应来确认连接状态。 - 超时处理:如果在一定时间内没有收到心跳响应,认为连接已断开,触发重连机制。
3. 重连机制
- 自动重连:在连接断开时(如网络问题、服务器故障等),自动尝试重新建立连接。
- 重连策略:可以设置重连的间隔时间(如指数退避策略),避免频繁重连导致的资源浪费。
- 重连次数限制:设置最大重连次数,避免无限重连。
4. 消息队列
- 消息缓存:在连接断开时,将未发送的消息缓存起来。
- 消息重发:在连接重新建立后,从队列中取出缓存的消息并重新发送。
5. 错误处理
- 捕获错误:捕获 WebSocket 连接过程中可能出现的错误(如网络异常、服务器拒绝连接等)。
- 日志记录:记录错误信息,便于调试和排查问题。
- 用户提示:向用户展示错误信息,提示用户当前状态(如“网络连接失败,请检查网络”)。
6. 资源管理
- 内存管理:确保在连接关闭时释放相关资源,避免内存泄漏。
- 线程管理:合理管理 WebSocket 的工作线程,避免线程资源耗尽。
7. 安全性
- 加密通信:使用
wss://(WebSocket Secure)协议,通过 TLS/SSL 加密数据传输,确保通信安全。 - 身份验证:在建立连接时进行身份验证,确保只有合法用户可以连接到服务器。
- 数据校验:对发送和接收的数据进行校验,防止恶意数据注入。
8. 状态同步
- 同步状态:在连接重新建立后,同步客户端和服务器的状态,确保数据一致性。
- 消息确认:对于重要消息,实现消息确认机制,确保消息被正确接收。
示例代码
1. 添加依赖
在 build.gradle 文件中添加 OkHttp 的依赖:
dependencies {implementation 'com.squareup.okhttp3:okhttp:4.10.0'
}
2. WebSocket 客户端实现
代码注释
import android.os.Handler;
import android.os.Looper;
import android.util.Log;import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;import java.util.concurrent.TimeUnit;
import java.util.concurrent.ConcurrentLinkedQueue;public class WebSocketClient {private static final String TAG = "WebSocketClient"; // 日志标签private WebSocket webSocket; // 当前 WebSocket 连接private final OkHttpClient client = new OkHttpClient(); // OkHttp 客户端实例private final Handler handler = new Handler(Looper.getMainLooper()); // 用于在主线程中更新 UIprivate final Runnable heartbeatRunnable = new Runnable() { // 心跳检测任务@Overridepublic void run() {if (webSocket != null && webSocket.send("ping")) { // 发送心跳消息 "ping"handler.postDelayed(this, 5000); // 每5秒发送一次心跳}}};private final Runnable reconnectRunnable = new Runnable() { // 重连任务@Overridepublic void run() {connect(url, callback); // 重新连接}};private final ConcurrentLinkedQueue<String> messageQueue = new ConcurrentLinkedQueue<>(); // 消息队列private final Object lock = new Object(); // 同步锁private String url; // WebSocket 服务器的 URLprivate WebSocketCallback callback; // WebSocket 回调接口public interface WebSocketCallback { // WebSocket 回调接口void onOpen(); // 连接成功void onMessage(String text); // 接收到消息void onClose(); // 连接关闭void onFailure(Throwable t); // 发生错误}public WebSocketClient(String url, WebSocketCallback callback) {this.url = url; // 初始化 URLthis.callback = callback; // 初始化回调接口}public void connect() { // 建立 WebSocket 连接Request request = new Request.Builder().url(url).build();webSocket = client.newWebSocket(request, new WebSocketListener() {@Overridepublic void onOpen(WebSocket webSocket, okhttp3.Response response) {super.onOpen(webSocket, response);Log.d(TAG, "WebSocket connected"); // 日志记录连接成功callback.onOpen(); // 调用回调接口的 onOpen 方法handler.post(heartbeatRunnable); // 启动心跳检测synchronized (lock) {while (!messageQueue.isEmpty()) { // 发送消息队列中的消息webSocket.send(messageQueue.poll());}}}@Overridepublic void onMessage(WebSocket webSocket, String text) {super.onMessage(webSocket, text);Log.d(TAG, "Received message: " + text); // 日志记录接收到的消息callback.onMessage(text); // 调用回调接口的 onMessage 方法if ("pong".equals(text)) { // 如果收到服务器的 "pong" 响应// 收到服务器响应,重置心跳检测handler.removeCallbacks(heartbeatRunnable);handler.post(heartbeatRunnable);}}@Overridepublic void onClosed(WebSocket webSocket, int code, String reason) {super.onClosed(webSocket, code, reason);Log.d(TAG, "WebSocket closed: " + reason); // 日志记录连接关闭callback.onClose(); // 调用回调接口的 onClose 方法handler.removeCallbacks(heartbeatRunnable); // 停止心跳检测handler.postDelayed(reconnectRunnable, 5000); // 5秒后重连}@Overridepublic void onFailure(WebSocket webSocket, Throwable t, okhttp3.Response response) {super.onFailure(webSocket, t, response);Log.e(TAG, "WebSocket error: " + t.getMessage()); // 日志记录错误信息callback.onFailure(t); // 调用回调接口的 onFailure 方法handler.removeCallbacks(heartbeatRunnable); // 停止心跳检测handler.postDelayed(reconnectRunnable, 5000); // 5秒后重连}});}public void sendMessage(String message) { // 发送消息synchronized (lock) {if (webSocket != null) {webSocket.send(message); // 如果连接已建立,直接发送消息} else {messageQueue.add(message); // 如果连接未建立,将消息加入队列}}}public void disconnect() { // 关闭 WebSocket 连接if (webSocket != null) {webSocket.close(1000, "Goodbye"); // 关闭连接}handler.removeCallbacks(heartbeatRunnable); // 停止心跳检测handler.removeCallbacks(reconnectRunnable); // 停止重连}
}
功能标注
-
连接管理:
connect()方法:建立 WebSocket 连接。disconnect()方法:关闭 WebSocket 连接。
-
心跳检测:
heartbeatRunnable:定期发送心跳消息"ping"。- 在
onMessage()方法中,收到"pong"响应时重置心跳检测。
-
重连机制:
reconnectRunnable:在连接关闭或发生错误时,5秒后自动尝试重新连接。
-
消息队列:
messageQueue:在连接未建立时,将消息加入队列。- 在
onOpen()方法中,从队列中取出消息并发送。
-
错误处理:
- 在
onFailure()方法中,记录错误信息并调用回调接口的onFailure()方法。
- 在
-
资源管理:
- 在
disconnect()方法中,停止心跳检测和重连任务,释放资源。
- 在
-
安全通信:
- 使用
wss://协议(WebSocket Secure)确保通信安全。
- 使用
-
状态同步:
- 在
onOpen()方法中,发送消息队列中的消息,确保消息不丢失。 - 在
onMessage()方法中,调用回调接口的onMessage()方法,同步接收到的消息。
- 在
3. 安卓端使用
MainActivity.java
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;import java.util.concurrent.TimeUnit;public class MainActivity extends AppCompatActivity {private WebSocketClient webSocketClient;private EditText messageEditText;private Button sendButton;private TextView messageTextView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);messageEditText = findViewById(R.id.message);sendButton = findViewById(R.id.send);messageTextView = findViewById(R.id.messageTextView);webSocketClient = new WebSocketClient("wss://yourserver.com/chat", new WebSocketClient.WebSocketCallback() {@Overridepublic void onOpen() {Log.d("WebSocket", "Connected");runOnUiThread(() -> messageTextView.setText("Connected"));}@Overridepublic void onMessage(String text) {Log.d("WebSocket", "Received: " + text);runOnUiThread(() -> messageTextView.setText("Received: " + text));}@Overridepublic void onClose() {Log.d("WebSocket", "Disconnected");runOnUiThread(() -> messageTextView.setText("Disconnected"));}@Overridepublic void onFailure(Throwable t) {Log.e("WebSocket", "Error: " + t.getMessage());runOnUiThread(() -> messageTextView.setText("Error: " + t.getMessage()));}});webSocketClient.connect();sendButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String message = messageEditText.getText().toString();if (!message.isEmpty()) {webSocketClient.sendMessage(message);messageEditText.setText("");}}});}@Overrideprotected void onDestroy() {super.onDestroy();webSocketClient.disconnect();}
}
布局文件(activity_main.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><EditTextandroid:id="@+id/message"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Enter message" /><Buttonandroid:id="@+id/send"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Send" /><TextViewandroid:id="@+id/messageTextView"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Status" />
</LinearLayout>
4. 后端(Flask + Flask-SocketIO)
安装依赖
pip install flask flask-socketio eventlet
Flask 应用代码(app.py)
from flask import Flask, render_template
from flask_socketio import SocketIO, sendapp = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)@app.route('/')
def index():return render_template('index.html')@socketio.on('message')
def handle_message(data):print('Received message: ', data)send(data, broadcast=True)if __name__ == '__main__':socketio.run(app, debug=True, host='0.0.0.0', port=5000)
5. 运行
- 启动 Flask 应用:
python app.py - 启动 Android 应用:
- 输入消息并点击发送,消息将通过 WebSocket 发送到服务器。
- 服务器将消息广播给所有连接的客户端,客户端接收到消息后显示在界面上。
相关文章:
使WebSocket 稳定可靠,需要考虑的方向
文章目录 1. 连接管理2. 心跳检测3. 重连机制4. 消息队列5. 错误处理6. 资源管理7. 安全性8. 状态同步 示例代码1. 添加依赖2. WebSocket 客户端实现代码注释功能标注3. 安卓端使用MainActivity.java布局文件(activity_main.xml) 4. 后端(Fla…...
Linux:进程:进程调度
进程在CPU上运行具有以下特性: 竞争、独⽴、并⾏、并发 竞争性:系统进程数⽬众多,⽽CPU资源很少甚至只有一个,所以进程之间是具有竞争属性的。为 了⾼效完成任务,更合理竞争相关资源,便具有了优先级 独⽴性: 为了避…...
Stable Diffusion 图像生成 GUI 应用:图像缩放等五个优化——SD界面学习记录
本篇续前面Stable DiffusionPyqt5实现图像生成和管理界面,链接如下: Stable DiffusionPyqt5: 实现图像生成与管理界面(带保存 历史记录 删除功能)——我的实验记录(结尾附系统效果图)-CSDN博客…...
职坐标解码互联网行业转型发展新动能
当前,互联网行业正以前所未有的速度重塑全球产业格局。工信部最新数据显示,我国互联网企业营收连续三年保持双位数增长,其中百强企业在人工智能、物联网等领域的投入强度同比提升40%,展现出强劲的技术引领力。与此同时,…...
【含文档+PPT+源码】基于微信小程序的非遗文化黄梅戏宣传平台的设计与实现
课程目标: 教你从零开始部署运行项目,学习环境搭建、项目导入及部署,含项目源码、文档、数据库、软件等资料 课程简介: 本课程演示的是一款基于微信小程序的非遗文化黄梅戏宣传平台的设计与实现,主要针对计算机相关…...
Causal Attention的底层原理
Causal Attention Transformer的Decoder中最显著的结构是Casual Attention。 通过本篇文章,你将学会 Casual Attention的机制原理 Casual Attention在TensorFlow中的实现原理 如何快速地保存并打印TensorFlow中模型已经训练好的参数 如何实现Transformer的Dec…...
深入理解类:ArkTS面向对象编程的核心概念
# 深入理解类:ArkTS面向对象编程的核心概念 在编程世界里,面向对象编程(OOP)是一种强大的编程范式,而类则是OOP的核心构建块。在ArkTS语言中,类的设计和使用对于构建复杂、可维护的应用程序至关重要。今天…...
AI 驱动下的后端开发架构革命:从智能协同体系
AI 驱动下的后端开发架构革命:从智能协同体系 一、引言:AI 重构后端开发范式 在 2025 年的企业级技术演进中,人工智能正从辅助工具升级为核心架构要素。根据 Gartner《2025 智能技术栈成熟度报告》,传统 "人力编码 硬规则…...
vue3 Ts axios 封装
vue3 Ts axios 封装 axios的封装 import axios, { AxiosError, AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosRequestConfig, AxiosHeaders } from axios import qs from qs import { config } from ./config import { ElMessage } from element-plus// …...
CyberAgentAILab 开源数字人项目TANGO,heygen的开源版来了~
简介 TANGO 是 CyberAgentAILab 开源的一项前沿研究成果,其初衷在于探索高效生成模型在实际应用场景中的表现。项目诞生于 CyberAgent 在整合创意与人工智能的实践中,旨在为数字内容生成、交互和实时渲染等领域提供一个高性能、模块化、可扩展的解决方案…...
ROS ROS2 机器人深度相机激光雷达多传感器标定工具箱入门教程(一)
系列文章目录 目录 系列文章目录 前言 一、安装 1.1 ROS 2 官方软件包 二、教程 2.1 标定配置器 2.1.1 机器人选项 2.1.2.1 外参相机-激光雷达标定 2.1.2.2 外参激光雷达-激光雷达标定 2.1.2.3 外参相机参照标定 2.1.2.4 外参激光雷达-参考标定 2.2 外参照相机-激…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(6):ながら 一边。。一边
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(6):ながら 一边。。一边 1、前言(1)情况说明(2)工程师的信仰 2、知识点(1)ながら1)一边。。一边2࿰…...
从EOF到REOF:如何用旋转经验正交函数提升时空数据分析精度?
目录 1. 基本概念与原理2. 应用场景3. 与传统EOF的区别4. 技术实现5. 其他领域中的“REOF”参考资料 REOF 的输入是多个地区在不同时间的气候数据(如温度或降雨量),它的作用是通过旋转计算找出这些数据中最主要的变化规律,输出则是…...
【HDFS入门】HDFS与Hadoop生态的深度集成:与YARN、MapReduce和Hive的协同工作原理
目录 引言 1 HDFS核心架构回顾 2 HDFS与YARN的集成 3 HDFS与MapReduce的协同 4 HDFS与Hive的集成 4.1 Hive架构与HDFS交互 4.2 Hive数据组织 4.3 Hive查询执行流程 5 HDFS在生态系统中的核心作用 6 性能优化实践 7 总结 引言 在大数据领域,Hadoop生态系统…...
用 AI 十天开发小程序:探秘 “幸运塔塔屋” 之 “解惑指南书” 功能
在当今软件开发领域,AI 技术正以前所未有的速度改变着我们的开发方式。我仅用十天时间,借助 AI 成功开发出 “幸运塔塔屋” 小程序,其中 “解惑指南书” 功能别具一格。今天,就为大家详细剖析这个功能从构思到落地的全过程。 十天…...
直流电源基本原理
整流电路 在构建整流电路时,要选择合适参数的二极管 If是二极管能够通过电流的能力,也是最大整流的平均电流。 还要考虑二极管的反向截至电压。 脉动系数电压交流幅值/直流平均电压(越小越好) 三相整流电路优点: …...
osu ai 论文笔记 DQN
e https://theses.liacs.nl/pdf/2019-2020-SteeJvander.pdf Creating an AI for the Rhytm Game osu! 20年的论文 用监督学习训练移动模型100首歌能达到95准确率 点击模型用DQN两千首歌65准确率 V抖用的居然不是强化学习? 5,6星打96准确度还是有的东西的 这是5.…...
MapReduce实验:分析和编写WordCount程序(对文本进行查重)
实验环境:已经部署好的Hadoop环境 Hadoop安装、配置与管理_centos hadoop安装-CSDN博客 实验目的:对输入文件统计单词频率 实验过程: 1、准备文件 test.txt文件,它是你需要准备的原始数据文件,存放在你的 Linux 系…...
Windows Acrobat Pro DC-v2025.001.20435-x64-CN-Portable便携版
Windows Acrobat Pro 链接:https://pan.xunlei.com/s/VOO1nMjQ1Qf53dyISGne0c_9A1?pwdsfgn# Acrobat Pro 2024 专业增强版特色 ● 创建和编辑 PDF 文件:可以将各种类型的文档转换为 PDF 格式,并进行编辑和修改。 ● 合并和拆分 PDF&#…...
二十、FTP云盘
1、服务端 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <netinet/in.h>…...
【4】k8s集群管理系列--harbor镜像仓库本地化搭建
一、harbor基本概念 Harbor是一个由VMware开源的企业级Docker镜像仓库解决方案,旨在解决企业在容器化应用部署中的痛点,提供镜像存储、管理、安全和分发的全生命周期管理。Harbor扩展了Docker Registry,增加了企业级功能,如…...
Oracle 12.1.0.2补丁安装全流程
第一步,先进行备份 tar -cvf u01.tar /u01 第二步,更新OPatch工具包 根据补丁包中readme信息汇总提示的信息,下载对应版本的OPatch工具包,本次下载的版本为: p6880880_122010_Linux-x86-64.zip opatch版本为最新的…...
【AAOS】【源码分析】Car UX Restrictions
AAOS UX的核心理念:安全驾驶是驾驶员的首要责任。汽车制造商和应用程序开发人员的所有设计都必须反映这一优先事项。 AAOS平台允许设备制造商(OEM)对不同驾驶状态下的限制进行定制。 驾驶员分心指南 只有符合Driver Distraction Guidelines的应用才可以在驾驶过程中运行。…...
解读《人工智能指数报告 2025》:洞察 AI 发展新态势
美国斯坦福大学 “以人为本人工智能研究院”(HAI)近日发布的第八版《人工智能指数报告》(AI Index Report 2025)备受全球瞩目。自 2017 年首次发布以来,该报告一直为政策制定者、研究人员、企业高管和公众提供准确、严…...
【SpringBoot+Vue自学笔记】003 SpringBoot Controll
跟着这位老师学习的:https://www.bilibili.com/video/BV1nV4y1s7ZN?vd_sourceaf46ae3e8740f44ad87ced5536fc1a45 这段话的意思其实是:Spring Boot 简化了传统 Web 项目的搭建流程,让你少折腾配置,直接开搞业务逻辑。 ὒ…...
探索Web3平台的数据安全和保护机制
在数字化时代,Web3 平台以其去中心化、透明性和用户主权等特点,正逐渐成为互联网技术的新宠。然而,随着数据价值的日益凸显,Web3 平台的数据安全和保护机制变得尤为重要。本文将深入探讨 Web3 平台的数据安全和保护机制࿰…...
基于ssh密钥访问远程Linux
1、在本地机器上生成密钥对(默认保存在 ~/.ssh/) ssh-keygen -t ed25519 或使用 RSA(兼容性更好): ssh-keygen -t rsa -b 4096 2、 将公钥上传到远程主机 方法一:使用 ssh-copy-id ssh-copy-id -i ~/.ssh/id_ed25519.pub us…...
《基于神经网络实现手写数字分类》
《基于神经网络实现手写数字分类》 一、主要内容: 1、通过B站陈云霁老师的网课,配合书本资料,了解神经网络的基本组成和数学原理。 2、申请云平台搭建实验环境 3、基于5个不同的实验模块逐步理解实验操作步骤,并实现不同模块代码…...
1 cline 提示词工程指南-架构篇
cline 提示词工程指南-架构篇 本篇是 cline 提示词工程指南的学习和扩展,可以参阅: https://docs.cline.bot/improving-your-prompting-skills/prompting 前言 cline 是 vscode 的插件,用来在 vscode 里实现 ai 编程。 它使得你可以接入…...
代理模式简述
目录 一、主要角色 二、类型划分 三、静态代理 示例 缺点 四、动态代理 JDK动态代理 示例 缺点 CGLib动态代理 导入依赖 示例 五、Spring AOP 代理模式是一种结构型设计模式,通过代理对象控制对目标对象的访问,可在不改变目标对象情况下增强…...
