OkHttp SSE 模块详解

OkHttp SSE 模块详解

什么是 Server-Sent Events (SSE)

Server-Sent Events (SSE) 是一种基于 HTTP 的服务器推送技术,允许服务器通过单个 HTTP 连接向客户端发送事件流。SSE 建立了一个长连接,服务器可以通过这个连接持续地向客户端推送数据,而无需客户端重复发起请求。

核心特点

  • 单向通信:服务器向客户端推送数据,客户端不能通过同一连接向服务器发送数据

  • 基于 HTTP :使用标准 HTTP 协议,Content-Type 为 text/event-stream

  • 自动重连:客户端在连接断开后会自动尝试重新连接

  • 事件 ID:支持事件 ID,可以在重连后恢复之前的状态

  • 基于纯文本:使用简单的文本格式传输数据

SSE 数据格式示例

vbnet 复制代码
event: userconnect
data: {"username": "bobby", "time": "02:33:48"}
id: 1

event: usermessage
data: {"username": "bobby", "message": "Hi everyone!"}
id: 2

SSE vs WebSocket

特性 SSE WebSocket
通信方向 单向(服务器到客户端) 双向
协议 HTTP WebSocket(初始握手基于HTTP)
复杂度 简单 相对复杂
自动重连 原生支持 需要自行实现
数据格式 文本 文本或二进制
跨域限制 受同源策略限制 较少限制
适用场景 实时通知、新闻推送、股票行情 聊天应用、多人游戏、协作工具

OkHttp SSE 模块的功能和用途

OkHttp SSE 模块是 OkHttp 库的扩展,提供了在 Android 和 Java 应用中使用 SSE 的能力。它封装了 SSE 的连接建立、事件解析和错误处理等复杂逻辑,让开发者可以简单地实现服务器推送功能。

主要功能

  1. 建立 SSE 连接:通过 HTTP 请求建立与 SSE 服务器的连接

  2. 事件解析:解析服务器发送的事件流,提取事件类型、数据和ID

  3. 自动重连:在连接断开时自动重新连接

  4. 事件监听:通过 EventSourceListener 接收和处理事件

  5. 连接管理:提供取消连接的方法

使用场景

SSE 技术和 OkHttp SSE 模块适用于以下场景:

  1. 实时通知系统:如新邮件提醒、系统通知等

  2. 实时数据更新:股票价格、体育比分、天气更新等

  3. 社交媒体动态:新的评论、点赞、关注等通知

  4. 日志流:实时查看服务器日志

  5. 进度更新:长时间运行任务的进度报告

优势

  1. 简单易用:相比 WebSocket,SSE 实现更简单,API 更直观

  2. HTTP 兼容:使用标准 HTTP,可以利用现有的 HTTP 基础设施(代理、缓存等)

  3. 轻量级:协议简单,资源消耗较小

  4. 自动重连:内置重连机制,提高了连接的可靠性

  5. 与 OkHttp 集成:可以复用 OkHttp 的连接池、拦截器等功能

代码示例

以下是使用 OkHttp SSE 模块的完整示例:

kotlin 复制代码
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.sse.EventSource
import okhttp3.sse.EventSourceListener
import okhttp3.sse.EventSources
import java.util.concurrent.TimeUnit

fun main() {
    // 1. 创建 OkHttpClient
    val client = OkHttpClient.Builder()
        .connectTimeout(30, TimeUnit.SECONDS)
        .readTimeout(90, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .build()
    
    // 2. 创建 EventSource.Factory
    val factory = EventSources.createFactory(client)
    
    // 3. 创建 Request
    val request = Request.Builder()
        .url("https://example.com/sse-endpoint")
        .header("Accept", "text/event-stream")
        .build()
    
    // 4. 创建 EventSourceListener
    val listener = object : EventSourceListener() {
        override fun onOpen(eventSource: EventSource, response: Response) {
            println("SSE connection opened: ${response.code}")
        }
        
        override fun onEvent(
            eventSource: EventSource,
            id: String?,
            type: String?,
            data: String
        ) {
            println("Event received:")
            println("  id: $id")
            println("  type: $type")
            println("  data: $data")
            
            // 处理不同类型的事件
            when (type) {
                "update" -> handleUpdate(data)
                "notification" -> showNotification(data)
                null -> handleDefaultEvent(data)
            }
        }
        
        override fun onClosed(eventSource: EventSource) {
            println("SSE connection closed normally")
        }
        
        override fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?) {
            println("SSE connection failed: ${t?.message}")
            response?.let { println("Response code: ${it.code}") }
            
            // 可以在这里实现自定义的重连逻辑
        }
    }
    
    // 5. 创建并启动 EventSource
    val eventSource = factory.newEventSource(request, listener)
    
    // 应用运行...
    
    // 6. 在适当的时候取消连接
    // eventSource.cancel()
}

// 事件处理函数
fun handleUpdate(data: String) {
    println("Processing update: $data")
}

fun showNotification(data: String) {
    println("Showing notification: $data")
}

fun handleDefaultEvent(data: String) {
    println("Processing default event: $data")
}

OkHttp SSE 实现原理

OkHttp 的 SSE 模块通过以下组件和流程实现 SSE:

核心组件

  1. EventSource 接口:定义 SSE 连接的基本操作

  2. EventSourceListener:处理连接状态和接收事件的回调

  3. RealEventSource:EventSource 的实际实现

  4. ServerSentEventReader:解析 SSE 事件流

实现流程

  1. 连接建立
  • RealEventSource 使用 OkHttp 的 Call 接口发起 HTTP 请求

  • 验证响应的 Content-Type 是否为 text/event-stream

  • 建立长连接并获取响应体的 Source

  1. 事件解析
  • ServerSentEventReaderSource 读取数据

  • 按照 SSE 规范解析事件行(event、data、id、retry)

  • 当收集到完整事件时,通过 EventSourceListener.onEvent() 回调通知客户端

  1. 自动重连
  • 当连接断开时,根据服务器指定的 retry 值或默认值进行重连

  • 重连时携带上次接收到的最后一个事件 ID,服务器可以据此发送错过的事件

  1. 错误处理
  • 网络错误、解析错误等通过 EventSourceListener.onFailure() 通知客户端

  • 客户端可以在此实现自定义的错误处理和重连策略

  1. 资源释放
  • 当调用 EventSource.cancel() 或发生不可恢复的错误时

  • 关闭网络连接,释放相关资源

  • 通过 EventSourceListener.onClosed()onFailure() 通知客户端

关键实现细节

  • 线程处理:事件解析和回调在 OkHttp 的后台线程池中进行,避免阻塞主线程

  • 缓冲管理:使用 Okio 库高效处理 I/O 操作和缓冲区管理

  • 连接复用:利用 OkHttp 的连接池机制,可能复用底层 TCP 连接

  • 拦截器兼容:完全兼容 OkHttp 的拦截器链,支持日志、认证等功能

通过这种实现,OkHttp SSE 模块提供了一个高效、可靠且易于使用的 SSE 客户端,同时充分利用了 OkHttp 的网络处理能力和扩展性。

相关推荐
Yang-Never5 小时前
Kotlin协程 -> Job.join() 完整流程图与核心源码分析
android·开发语言·kotlin·android studio
一笑的小酒馆11 小时前
Android性能优化之截屏时黑屏卡顿问题
android
懒人村杂货铺13 小时前
Android BLE 扫描完整实战
android
TeleostNaCl15 小时前
如何安装 Google 通用的驱动以便使用 ADB 和 Fastboot 调试(Bootloader)设备
android·经验分享·adb·android studio·android-studio·android runtime
fatiaozhang952716 小时前
中国移动浪潮云电脑CD1000-系统全分区备份包-可瑞芯微工具刷机-可救砖
android·网络·电脑·电视盒子·刷机固件·机顶盒刷机
2501_9159184117 小时前
iOS 开发全流程实战 基于 uni-app 的 iOS 应用开发、打包、测试与上架流程详解
android·ios·小程序·https·uni-app·iphone·webview
lichong95117 小时前
【混合开发】vue+Android、iPhone、鸿蒙、win、macOS、Linux之dist打包发布在Android工程asserts里
android·vue.js·iphone
Android出海17 小时前
Android 15重磅升级:16KB内存页机制详解与适配指南
android·人工智能·新媒体运营·产品运营·内容运营
一只修仙的猿17 小时前
毕业三年后,我离职了
android·面试
编程乐学18 小时前
安卓非原创--基于Android Studio 实现的新闻App
android·ide·android studio·移动端开发·安卓大作业·新闻app