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 的连接建立、事件解析和错误处理等复杂逻辑,让开发者可以简单地实现服务器推送功能。
主要功能
-
建立 SSE 连接:通过 HTTP 请求建立与 SSE 服务器的连接
-
事件解析:解析服务器发送的事件流,提取事件类型、数据和ID
-
自动重连:在连接断开时自动重新连接
-
事件监听:通过 EventSourceListener 接收和处理事件
-
连接管理:提供取消连接的方法
使用场景
SSE 技术和 OkHttp SSE 模块适用于以下场景:
-
实时通知系统:如新邮件提醒、系统通知等
-
实时数据更新:股票价格、体育比分、天气更新等
-
社交媒体动态:新的评论、点赞、关注等通知
-
日志流:实时查看服务器日志
-
进度更新:长时间运行任务的进度报告
优势
-
简单易用:相比 WebSocket,SSE 实现更简单,API 更直观
-
HTTP 兼容:使用标准 HTTP,可以利用现有的 HTTP 基础设施(代理、缓存等)
-
轻量级:协议简单,资源消耗较小
-
自动重连:内置重连机制,提高了连接的可靠性
-
与 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:
核心组件
-
EventSource 接口:定义 SSE 连接的基本操作
-
EventSourceListener:处理连接状态和接收事件的回调
-
RealEventSource:EventSource 的实际实现
-
ServerSentEventReader:解析 SSE 事件流
实现流程
- 连接建立:
-
RealEventSource
使用 OkHttp 的Call
接口发起 HTTP 请求 -
验证响应的 Content-Type 是否为
text/event-stream
-
建立长连接并获取响应体的
Source
- 事件解析:
-
ServerSentEventReader
从Source
读取数据 -
按照 SSE 规范解析事件行(event、data、id、retry)
-
当收集到完整事件时,通过
EventSourceListener.onEvent()
回调通知客户端
- 自动重连:
-
当连接断开时,根据服务器指定的
retry
值或默认值进行重连 -
重连时携带上次接收到的最后一个事件 ID,服务器可以据此发送错过的事件
- 错误处理:
-
网络错误、解析错误等通过
EventSourceListener.onFailure()
通知客户端 -
客户端可以在此实现自定义的错误处理和重连策略
- 资源释放:
-
当调用
EventSource.cancel()
或发生不可恢复的错误时 -
关闭网络连接,释放相关资源
-
通过
EventSourceListener.onClosed()
或onFailure()
通知客户端
关键实现细节
-
线程处理:事件解析和回调在 OkHttp 的后台线程池中进行,避免阻塞主线程
-
缓冲管理:使用 Okio 库高效处理 I/O 操作和缓冲区管理
-
连接复用:利用 OkHttp 的连接池机制,可能复用底层 TCP 连接
-
拦截器兼容:完全兼容 OkHttp 的拦截器链,支持日志、认证等功能
通过这种实现,OkHttp SSE 模块提供了一个高效、可靠且易于使用的 SSE 客户端,同时充分利用了 OkHttp 的网络处理能力和扩展性。