okhttp的WebSocket心跳实现原理

embedded/2024/12/22 9:05:24/

okhttpWebSocket_2">okhttp的WebSocket实现心跳包需要服务端新增协议吗

‌不需要。‌

OkHttp的WebSocket实现已经内置了心跳包机制,通过PING/PONG帧来维持连接保活。这意味着,OkHttp的WebSocket客户端和服务端在通信过程中,会自动发送PING/PONG帧来检测连接的活跃状态,无需服务端新增任何协议或特别处理。这种机制确保了即使在没有数据传输的情况下,连接也能保持活跃,防止因为长时间没有通信而导致连接被意外关闭。因此,使用OkHttp进行WebSocket通信时,服务端不需要做任何特别的处理来实现心跳包功能‌1。

此外,WebSocket协议本身已经设计了心跳机制,这个功能用于检测链接是否可用。虽然心跳功能不一定支持携带数据,具体实现可能会有所不同,但基本的心跳检测功能已经包含在WebSocket协议中,无需服务端额外实现‌

WebSocket协议 的PING/PONG机制

WebSocket 的 PING/PONG 是一种保持连接活跃的机制。当服务器需要检查客户端是否仍然在线,或者客户端需要检查服务器是否在线时,它们可以相互发送 PING 消息。对方需要回复 PONG 消息以证明自己在线。

PING 是一个控制帧,用于检测对端是否在线,PONG 是对 PING 的响应。PING 可以携带数据,PONG 必须不携带数据

okhttpWebSocket_18">okhttp的WebSocket添加心跳

首先,我来简单梳理一下okhttp中心跳的实现原理,如果只是想要解决方法的朋友可以直接跳过这一部分。

okhttp中,实现心跳的方式非常简单,只需要在OkHttpClient创建时添加相应的配置即可:

  OkHttpClient.Builder().pingInterval(HEART_BEAT_RATE, TimeUnit.SECONDS).build()

okhttpWebSocket_29">okhttp的WebSocket的心跳实现原理

    //OkHttpClient.java@Override public WebSocket newWebSocket(Request request, WebSocketListener listener) {RealWebSocket webSocket = new RealWebSocket(request, listener, new Random(), pingInterval);webSocket.connect(this);return webSocket;}
   //RealWebSocket.javapublic RealWebSocket(Request request, WebSocketListener listener, Random random,long pingIntervalMillis) {//...this.pingIntervalMillis = pingIntervalMillis;//...}public void initReaderAndWriter(String name, Streams streams) throws IOException {synchronized (this) {//...this.executor = new ScheduledThreadPoolExecutor(1, Util.threadFactory(name, false));if (pingIntervalMillis != 0) {executor.scheduleAtFixedRate(new PingRunnable(), pingIntervalMillis, pingIntervalMillis, MILLISECONDS);}//...}}private final class PingRunnable implements Runnable {@Override public void run() {writePingFrame();}}void writePingFrame() {//...try {writer.writePing(ByteString.EMPTY);} catch (IOException e) {failWebSocket(e, null);}//...}//WebSocketWriter.javavoid writePing(ByteString payload) throws IOException {writeControlFrame(OPCODE_CONTROL_PING, payload);}

上面的代码就是ping的主要发送逻辑了,简单总结一下就是如果pingInterval不为0,那就开启一个的循环任务,定时的去发送代表ping的ControlFrame。

其中值得一提的就是ControlFrame这个概念,在WebSocket中的frame分为两类,一类叫做MessageFrame,也就是平时客户端与服务端互相通信的部分。另一类叫做ControlFrame,其中包括CONTROL_PING,CONTROL_PONG,CONTROL_CLOSE,可以看出这一类更偏重与功能性的方面。具体为哪一类的Frame可以在Header中进行区分。

上面已经介绍了心跳的发送逻辑,那么下面就轮到接收的逻辑了,还是先来看看代码:

    //RealWebSocket.javapublic void loopReader() throws IOException {while (receivedCloseCode == -1) {// This method call results in one or more onRead* methods being called on this thread.reader.processNextFrame();}}//WebSocketReader.javavoid processNextFrame() throws IOException {readHeader();if (isControlFrame) {readControlFrame();} else {readMessageFrame();}}private void readControlFrame() throws IOException {//...switch (opcode) {case OPCODE_CONTROL_PING:frameCallback.onReadPing(controlFrameBuffer.readByteString());break;case OPCODE_CONTROL_PONG:frameCallback.onReadPong(controlFrameBuffer.readByteString());break;case OPCODE_CONTROL_CLOSE://...default:throw new ProtocolException("Unknown control opcode: " + toHexString(opcode));}}

可以看到,接收的部分逻辑也很简单,就是通过一个循环去读取,如果接收到了消息,那就先通过header确定frame的类型,然后再分类进行处理。

而且值得注意的是,上面代码中出现了一个frameCallback的对象,而这个对象是WebSocketReader.FrameCallback这个接口的实现,而里面的onReadPing和onReadPong就是我们之后能够做文章的地方了。

    WebSocketReader.FrameCallbackpublic interface FrameCallback {void onReadMessage(String text) throws IOException;void onReadMessage(ByteString bytes) throws IOException;void onReadPing(ByteString buffer);void onReadPong(ByteString buffer);void onReadClose(int code, String reason);}

okhttpWebSocket_139">okhttp的WebSocket的心跳超时会自动重连吗

‌OkHttp的WebSocket实现支持心跳超时自动重连。‌

OkHttp的WebSocket实现通过设置心跳间隔来检测连接状态。如果客户端在一段时间内没有收到服务器的响应,即心跳超时,它会认为连接断开,并触发断线重连机制。这个过程确保了与服务器的持续通信。
具体来说,OkHttp允许用户设置心跳间隔,例如,通过:[OkHttpClient.Builder].pingInterval()方法设置心跳间隔,这个方法允许用户指定心跳消息发送的频率。如果服务器在规定的时间内没有响应心跳消息,客户端会认为连接已断开,并尝试重新建立连接。这种机制对于保持长时间运行的WebSocket连接特别重要,因为它能够自动处理网络不稳定或临时中断的情况,从而保持应用的实时性和响应性。

此外,OkHttp还支持通过配置来设置重连间隔,例如,通过:[RxWebSocket]的配置来设置重连间隔,这为用户提供了更大的灵活性,可以根据应用的需求调整重连的策略。这种自动重连的功能对于提高应用的健壮性和用户体验非常重要,尤其是在网络条件不稳定的环境中‌。

相关内容:
okhttp的WebSocket添加心跳回调


http://www.ppmy.cn/embedded/102137.html

相关文章

深入理解Node.js:不只是JavaScript的后端环境

目录 摘要 1. Node.js 简介 2. Node.js 与 JavaScript 的关系 3. Node.js 的核心特性 4. Node.js 在后端开发中的应用 5. Node.js 的生态系统 6. Node.js 的性能优势 7. Node.js 的挑战与解决方案 8. 结合 Docker 和微服务 9. 实例:构建一个简单的 REST AP…

关于数据处理的思路·一点实践

一、如何设计适合的方案 不同的数据场景,切入角度不同,设计出来的方案也会很不一样,始终有更好的,我们只要在有限的资源下,设计出适合的方案即可。 下面贴出一份,批量处理数据的大致思路: 二、参…

【LLM之Data】SKYSCRIPT-100M论文阅读笔记

研究背景 随着短视频和短剧的兴起,自动化的剧本生成和短剧制作在影视行业中的需求逐渐增加。传统的剧本生成过程需要大量的人工干预,限制了其在规模和效率上的扩展性。当前的大型语言模型(LLM)在剧本生成方面展现出一定潜力&…

【计算阶乘求和】计算1!+3!+5!+...+n!/(n+1)!

输入一个正整数n&#xff1a; n为奇数&#xff0c;输出1&#xff01;3&#xff01;5&#xff01;...n&#xff01; n为偶数&#xff0c;输出1&#xff01;3&#xff01;5&#xff01;...&#xff08;n1&#xff09;&#xff01; 具体代码&#xff1a; #include<stdio.h>…

JVM 在GC 时的根对象都有那些

在 Java 的垃圾回收&#xff08;Garbage Collection&#xff0c;GC&#xff09;过程中&#xff0c;根对象&#xff08;Roots&#xff09;是用于判断哪些对象是可达的基础。根对象通常是一组特定的对象引用&#xff0c;从这些对象出发&#xff0c;GC 可以判断哪些对象仍然存活&a…

如果一个函数func定义在namespace sggk::test中,pre类定义在namespace sggk中,那么func能否调用类pre

在C中&#xff0c;如果一个函数func定义在命名空间sggk::test中&#xff0c;而类pre定义在命名空间sggk中&#xff0c;那么func函数可以调用pre类&#xff0c;但需要通过适当的命名空间解析来访问它。 有几种方式可以实现这一点&#xff1a; 使用完全限定名&#xff1a;在func函…

Dashboard Interface 应用

Dashboard Server Remote Control Interface&#xff08;简称Dashboard Interface&#xff09;是一个关键的功能&#xff0c;它为用户提供了通过TCP/IP协议远程控制机器人的能力&#xff0c;执行包括开关机、加载程序、检查机器人状态以及设置机器人操作模式等多种操作。 功能…

不动产登记证识别API开发文档、不动产登记证识别接口

调用客户端运行环境 当客户端使用的编程语言为Java时&#xff0c;请使用1.5及以上版本JRE。 服务主要功能描述&#xff1a;翔云不动产登记证识别&#xff0c;可自动、批量识别不动产登记证明中的权利人、共有情况、用途、权利性质、使用期限等文字信息。 1) 通过https协议po…