SSE协议解析

205 阅读2分钟

一、什么是SSE协议?

SSE,全称 Server-Sent Events(服务器发送事件),是一种允许服务器随时向客户端单向推送数据的技术。它基于标准的 HTTP 协议,客户端发起一个请求后,服务器会保持这个连接的持久打开,并可以随时通过这个连接将数据以流的形式发送给客户端。

二、SSE协议的核心特点

1.基于HTTP,简单易用

SSE建立在标准的HTTP协议之上,服务器通过设置特定的MIME类型(text/event-stream)来发送数据流。

2.服务器单向推送

SSE是单向通信,数据流从服务器流向客户端。服务器可以随时主动向客户端推送新消息。

3.自动重连机制

当网络连接意外中断时(如网络波动),EventSource API会自动尝试重新连接到服务器。

4.文本数据流

SSE被设计用于传输文本数据,二进制需进行Base64编码。

5.支持事件类型

服务器可以发送带有类型的事件,客户端可以监听特定类型的事件然后执行不同的操作。

三、 SSE 工作原理

添加依赖

implementation 'com.squareup.okhttp3:okhttp-sse:4.10.0'
class SSEClient(private val baseUrl: String) {

    private val okHttpClient = OkHttpClient.Builder()
        .readTimeout(0, TimeUnit.SECONDS)     // 读超时(SSE 需要设为 0)
        .build()

    private var eventSource: EventSource? = null

    // 创建 SSE 连接并返回数据流
    fun connectStream(): Flow<SSEEvent> = flow {
        val request = Request.Builder()
            .url(baseUrl)
            .header("Accept", "text/event-stream")
            .header("Cache-Control", "no-cache")
            .header("Connection", "keep-alive")
            .build()

        val eventSourceListener = object : EventSourceListener() {
            override fun onOpen(eventSource: EventSource, response: Response) {
                Log.d("SSEClient","SSE连接已建立")
            }

            override fun onEvent(
                eventSource: EventSource,
                id: String?,
                type: String?,
                data: String
            ) {
                Log.d("SSEClient","SSE事件.....$data")
            }

            override fun onClosed(eventSource: EventSource) {
                Log.d("SSEClient","SSE连接已关闭")
            }

            override fun onFailure(
                eventSource: EventSource,
                t: Throwable?,
                response: Response?
            ) {
                Log.d("SSEClient","SSE连接失败: ${response?.message}")
            }
        }

        // 创建 EventSource
        this@SSEClient.eventSource = EventSources.createFactory(okHttpClient)
            .newEventSource(request, eventSourceListener)
    }

    // 手动关闭连接
    fun disconnect() {
        eventSource?.cancel()
        eventSource = null
    }
}

// SSE 事件数据类
data class SSEEvent(
    val id: String? = null, // 事件id,断线重连后会在 `Last-Event-ID` 请求头中发送,服务器可根据这个id做断点续传。
    val type: String = "message", // 自定义事件类型
    val data: String, // 事件数据
)

四、SSE的应用场景

1.实时新闻或者信息流

2.社交媒体的通知推送

五、总结

SSE 是一个轻量、HTTP 原生、单向的实时推送解决方案——非常适合文本流、通知、新闻推送等单向场景;当需要双向通信或高频二进制数据时,应选择 WebSocket 或者更专业的协议。