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

摘要

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

技术原理: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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值