App模拟心跳长连接的实现方法demo

news2024/11/22 22:42:59

摘要

背景:心跳通常是指客户端或服务器定期发送一个小型的、空的消息以保持连接的活动状态。它用于检测连接是否仍然有效,并防止连接由于长时间没有活动而被关闭。

技术原理:App定时发消息给服务器,服务器回消息表示连接依旧有效

日志:

0

实现方法

1.服务端

建立WebSocket 服务器应用程序首先,添加以下依赖项到项目的

build.gradle 文件中:

dependencies {    implementation ("io.ktor:ktor-server-netty:1.6.3")    implementation ("io.ktor:ktor-websockets:1.6.3")    implementation ("ch.qos.logback:logback-classic:1.2.6")}

使用 Ktor 框架创建一个嵌入式 Netty 服务器。它监听本地的 8080 端口,并在

/ws 路径上处理 WebSocket 连接。

import io.ktor.application.*import io.ktor.http.cio.websocket.*import io.ktor.routing.*import io.ktor.server.engine.embeddedServerimport io.ktor.server.netty.Nettyimport io.ktor.websocket.WebSocketsimport io.ktor.websocket.webSocketimport kotlinx.coroutines.GlobalScopeimport kotlinx.coroutines.launchimport java.util.concurrent.atomic.AtomicIntegerfun main() {    embeddedServer(Netty, port = 8080, module = Application::module).start(wait = true)}fun Application.module() {    install(WebSockets)    routing {        val connections = AtomicInteger(0)        val clients = mutableListOf<WebSocketSession>()        webSocket("/ws") {            connections.incrementAndGet()            println("Client connected. Total connections: ${connections.get()}")            clients.add(this)            try {                for (frame in incoming) {                    when (frame) {                        is Frame.Text -> {                            val receivedText = frame.readText()                            println("Received message: $receivedText")                            send("Server received: $receivedText")                            // 在收到消息后,主动向所有客户端发送一条消息                            GlobalScope.launch {                                clients.forEach { client ->                                    client.send("Server broadcast: $receivedText")                                }                            }                        }                        else -> {}                    }                }            } catch (e: Exception) {                println("WebSocket error: ${e.message}")            } finally {                clients.remove(this)                connections.decrementAndGet()                println("Client disconnected. Total connections: ${connections.get()}")            }        }    }}

运行main函数即可,等App客户端连接即可

0

2.客户端

使用 Kotlin 编写的长连接示例代码,用于在 Android 应用程序中建立和保持长连接首先,添加以下依赖项到项目的

build.gradle 文件中:

implementation("org.java-websocket:Java-WebSocket:1.5.1")

创建一个

WebSocketClient 类,并实现相应的方法

package com.fadi.power.net.serviceimport android.util.Logimport com.fadi.power.net.config.Configimport com.fadi.power.net.utils.TimeUtilsimport org.java_websocket.client.WebSocketClientimport org.java_websocket.drafts.Draftimport org.java_websocket.handshake.ServerHandshakeimport java.net.URIimport java.util.concurrent.Executorsimport java.util.concurrent.ScheduledExecutorServiceimport java.util.concurrent.TimeUnitclass WebSocketClient(serverUri: URI, draft: Draft) : WebSocketClient(serverUri, draft) {    companion object {        const val HEARTBEAT_MESSAGE = "Heartbeat"    }    private var mEnableHeartbeat = false    private var heartbeatExecutor: ScheduledExecutorService? = null    override fun onOpen(handshakedata: ServerHandshake?) {        // 连接成功,发送数据或执行其他操作        send("Hello, Server!")        Log.d(Config.TAG, "WebSocketClient onOpen: Hello, Server!")        // 【不使用自带的心跳,使用自建Alarm定时】启动定时任务发送心跳消息        // startHeartbeat()    }    override fun onClose(code: Int, reason: String?, remote: Boolean) {        // 【不使用自带的心跳,使用自建Alarm定时】连接关闭,执行相应的处理逻辑        // 停止心跳任务        // stopHeartbeat()    }    override fun onMessage(message: String?) {        // 接收到服务器发送的消息,执行相应的处理逻辑        message?.let {            Log.d(Config.TAG, "WebSocketClient onMessage: Received message: $it")        }    }    override fun onError(ex: Exception?) {        // 连接出现错误,执行相应的错误处理逻辑        ex?.let {            Log.d(Config.TAG, "WebSocketClient onError: WebSocket error: ${it.message}")        }    }    private fun startHeartbeat() {        heartbeatExecutor = Executors.newSingleThreadScheduledExecutor()        heartbeatExecutor?.scheduleAtFixedRate(            { sendHeartbeat() },            0, // 初始延迟为0            1, // 间隔为1分钟            TimeUnit.MINUTES        )    }    private fun stopHeartbeat() {        heartbeatExecutor?.shutdownNow()        heartbeatExecutor = null    }    fun sendHeartbeat() {        if (!mEnableHeartbeat) {            return        }        val timestamp = System.currentTimeMillis()        val heartbeatMessage = "$HEARTBEAT_MESSAGE ${TimeUtils.timeStamp2Date(timestamp)}"        send(heartbeatMessage)        Log.d(Config.TAG, "WebSocketClient sendHeartbeat: Sending heartbeat message: $heartbeatMessage")    }    fun setEnableHeartbeat(enable: Boolean) {        mEnableHeartbeat = enable    }    fun isHeartbeat(): Boolean {        return mEnableHeartbeat    }}

应用启动时,它将连接到指定的 WebSocket 服务器,并在连接成功后发送一条消息

// 服务器ip: 把电脑当做服务器, ipconfig获取    const val SERVER_IP = "10.170.16.162"    const val SERVER_DOWNLOAD_PORT = "8000"    const val DOWN_LOAD_FILE_NAME =  "test.apk"    //http://10.170.16.162:8000/test.apk"    const val DOWN_LOAD_URL = "http:" + SERVER_IP + ":" + SERVER_DOWNLOAD_PORT + "/" + DOWN_LOAD_FILE_NAME    // 加密 wss://192.168.0.100:8080/ws    // 非加密 ws://10.170.16.162:8080/ws    const val SERVER_PUSH_PORT = "8080"    const val PUSH_URL = "ws://" + SERVER_IP + ":" + SERVER_PUSH_PORT + "/ws"        初始化        val serverUri = URI(Config.PUSH_URL)        val draft = Draft_6455() // 使用 WebSocket 协议版本 13        mWebSocketClient = WebSocketClient(serverUri, draft)        mWebSocketClient.connect()           private fun handleHeadBeatEvent(scene: String, checked: Boolean) {            // 心跳场景的处理逻辑            if (checked == true) {                // 开启心跳                Log.d(Config.TAG, "开启心跳")                enableOneMinuteAlarm()                mWebSocketClient.setEnableHeartbeat(true)                mAlarmNetWorkNotification.showNotification(scene)            } else {                // 关闭心跳                Log.d(Config.TAG, "关闭心跳")                disableOneMinuteAlarm()                mWebSocketClient.setEnableHeartbeat(false)                mAlarmNetWorkNotification.hideNotification(scene)            }        }

3.运行结果

支持设定心跳间隔,调试阶段定了了1分钟一次和服务端的心跳长连接

3.1 客户端打印

0

3.2 服务端打印

0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2198226.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手机竖屏 Premiere Pro 电影转场特效视频模板Pr工程文件

10个不同的类别和115个过渡。过渡很容易使用。随附视频教程。 下载地址&#xff1a;Pr模板网 下载链接&#xff1a;https://prmuban.com/40597.html

动态规划算法专题(五):子序列问题

目录 1、最长递增子序列 1.1 算法原理 1.2 算法代码 2、摆动序列 2.1 算法原理 2.2 算法代码 3、最长递增子序列的个数 3.1 算法原理 3.2 算法代码 4、最长数对链 4.1 算法原理 4.2 算法代码 5、最长定差子序列 5.1 算法原理 5.2 算法代码 6、最长的斐波那契子序…

NASA:气象追踪分子光谱(ATMOS)二级产品,包含在垂直高度(公里)网格上的微量气体

目录 简介 摘要 引用 网址推荐 0代码在线构建地图应用 机器学习 ATMOS L2 Trace Gases on Altitude Grid, Tab Delimited Format V3 (ATMOSL2AT) at GES DISC 简介 这是版本3的气象追踪分子光谱&#xff08;ATMOS&#xff09;二级产品&#xff0c;包含在垂直高度&#…

多线程股吧(东方财富)用户信息爬取

多线程东方财富&#xff08;股吧&#xff09;用户信息爬取 在上一篇博客股吧信息爬取的基础上加入了多线程&#xff0c;使得速度提升了十几倍&#xff0c;爬取内容如下&#xff1a; 最终爬取结果如下&#xff1a; 完整代码如下&#xff08;准备好环境&#xff0c;比如pytho…

安宝特案例 | Fundació Puigvert 医院应用AR技术开创尿石症治疗新纪元

案例介绍 在医疗科技不断进步的今天&#xff0c;Fundaci Puigvert 医院迈出了重要一步&#xff0c;成功应用AR技术进行了全球首例同时使用两台内窥镜的ECIRS手术&#xff08;内镜肾内联合手术&#xff09;&#xff0c;由Esteban Emiliani M.D. PhD F.E.B.U 博士主刀。这标志着…

yub‘s Algorithmic Adventures_Day7

环形链表 link&#xff1a;https://leetcode.cn/problems/linked-list-cycle-ii/description/ 思路分析 我只能说双指针yyds【刻板hh】 我们分两种情况来分析 起码在第二圈才会相遇 fast比slow多走环的整数倍 fast 走的步数是 slow 步数的 2 倍&#xff0c;即 f2s&#xff…

5.资源《Arduino UNO R3 proteus 使用CD4511驱动数码管工程文件(含驱动代码)》说明。

资源链接&#xff1a; Arduino UNO R3 proteus 使用CD4511驱动数码管工程文件&#xff08;含驱动代码&#xff09; 1.文件明细&#xff1a; 2.文件内容说明 包含&#xff1a;proteus工程&#xff0c;内含设计图和工程代码。 3.内容展示 4.简述 工程功能可以看这个视频 数码…

微信小程序流量主

开发小程序也已经有一段时间了,也是为了添加流量主来开发小程序,根据小程序的定位,来获取用户想要的资源,通过广告的形式来增加用户的点击量进行收益,收益虽然微不足道,但是也是很有成就感的

活动邀请 | SonarQube×创实信息即将亮相2024 GOPS全球运维大会-上海站,分享代码质量与安全提升策略

2024年10月18日-19日&#xff08;周五-周六&#xff09;&#xff0c;第二十四届 GOPS 全球运维大会上海站将在上海中庚聚龙酒店举办。 大会为期2天&#xff0c;侧重大模型、DevOps、SRE、AIOps、BizDevOps、云原生及安全等热门技术领域。特设了如大模型 运维/研发测试、银行/…

宠物咖啡馆服务平台:SpringBoot技术深度解析

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理基于Spring Boot的宠物咖啡馆平台的设计与…

2024_10_8 系统进展

改进位置 发现是label_api里藏了我需要改进的东西 settings.py 数据库 我这边电脑上使用的是windows 192 vue.config.js 陈家强是这样设置的 module.exports {publicPath: process.env.NODE_ENV production? /: /,assetsDir: static,// css: {// extract: false// },…

使用XML实现MyBatis的基础操作

目录 前言 1.准备工作 1.1⽂件配置 1.2添加 mapper 接⼝ 2.增删改查操作 2.1增(Insert) 2.2删(Delete) 2.3改(Update) 2.4查(Select) 前言 接下来我们会使用的数据表如下&#xff1a; 对应的实体类为&#xff1a;UserInfoMapper 所有的准备工作都在如下文章。 MyBati…

《大规模语言模型从理论到实践》第一轮学习--Fine-tuning微调

第一轮学习目标&#xff1a;了解大模型理论体系 第二轮学习目标&#xff1a;进行具体实操进一步深入理解大模型 从大语言模型的训练过程来理解微调 大预言模型训练主要包含四个阶段&#xff1a;预训练、有监督微调、奖励建模、强化学习。 预训练&#xff08;Pretraining&…

[paddle]paddleseg快速开始

快速开始 为了让大家快速了解PaddleSeg&#xff0c;本文档使用一个简单示例进行演示。在实际业务中&#xff0c;建议大家根据实际情况进行调整适配。 在开始下面示例之前&#xff0c;请大家确保已经安装好PaddleSeg开发环境&#xff08;安装说明&#xff09;。 1 准备数据 …

被AI坑的一天—CentOS7导入阿里云YUM源报错的 GPG密钥提示404

过于相信人工智能 配置YUM源根据AI的说法换阿里云的YUM源验证AI配置结果解决问题 配置YUM源 由于电脑受限制 , 不能访问境外网站,所以用不了centos自带的源 ,是报404的 根据AI的说法换阿里云的YUM源 编辑 /etc/yum.repos.d/CentOS-Base.repo ,更换为 配置完成后sudo yum …

nacos多数据源插件介绍以及使用

概述 在微服务架构中&#xff0c;服务配置的集中管理和动态调整是至关重要的。Nacos 提供了配置管理和服务发现的功能&#xff0c;其中配置管理支持动态数据源的切换&#xff0c;增强了其在复杂环境中的适用性。默认情况下&#xff0c;Nacos 支持 MySQL 和Derby&#xff0c;但…

C++——AVL树的模拟实现

目录 一、AVL树结点 二、AVL树结构 三、插入数据&#xff08;重点&#xff09; 1、右单旋 2、左单旋 3、左右双旋 4、右左双旋 AVL树是一颗平衡二叉搜索树&#xff0c;它的本质就是一颗之前说过的二叉搜索树。但是二叉搜索树可能会出现极端情况&#xff0c;导致二叉搜索树变…

不同时期的USB接口

Type-A Type-A接口最早于USB1.0标准(1996)推出&#xff0c;拥有四个引脚&#xff1a;VBUS提供5V电源&#xff0c;D-和D用于数据传输&#xff0c;GND接地。 Type-B Type-B接口最早于USB1.0标准(1996)推出&#xff0c;拥有四个引脚&#xff1a;VBUS提供5V电源&#xff0c;D-和D用…

QD1-P7 HTML常用标签:div和span

本节学习&#xff1a;div 和 span 标签。 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p7 ‍ 一、div 标签 用途 ​<div>​ 标签在 HTML 中是一个通用 容器 &#xff0c;用于将 HTML 文档中的内容分组并在文档中划分区域。<div> ​元素本身不具有特定的含…

道路积水检测数据集 1450张 路面积水 带分割 voc yolo

道路积水检测数据集 1450张 路面积水 带分割 voc yolo 分类名: (图片张数&#xff0c; 标注个数) puddle:(1468,1994) 总数:(1468&#xff0c;1994) 总类(nc): 1类 道路积水检测数据集介绍 项目名称 道路积水检测数据集 项目概述 本数据集包含1450张带有标注的图像&#x…