认识一下,轻量消息推送 Server-Sent Events

发布于:2025-02-11 ⋅ 阅读:(34) ⋅ 点赞:(0)

什么是 SSE(Server-Sent Events)

Server-Sent Events(简称 SSE)是一种在浏览器中实现单向实时通信的技术。它允许服务器通过 HTTP 持久连接向客户端发送实时更新的数据流。这种通信模式非常适用于需要频繁向客户端推送数据的场景,例如股票行情更新、实时聊天通知、社交媒体动态等。

SSE 基于 HTTP 协议,并以文本流的方式传递数据,使用的是标准的 text/event-stream MIME 类型。浏览器内置支持 SSE,无需额外的第三方库支持。

SSE 实现原理

SSE 的实现原理依赖于持久的 HTTP 连接:

  1. 客户端发起连接:客户端通过 HTTP 请求(通常是 GET 请求)向服务器发送一个持续连接的请求。
  2. 服务器保持连接:服务器接收到请求后,不关闭连接,而是以流的形式持续发送数据。
  3. 数据格式:服务器以 text/event-stream 格式推送数据,每条数据以换行符分隔,通常包含事件类型(event)和数据内容(data)。
  4. 自动重连:如果连接中断,浏览器会自动尝试重新连接。

一个典型的 SSE 数据流可能如下:

retry: 3000
id: 12345
event: message
data: {"content": "This is a server-sent message"}

SSE vs WebSocket

特性 SSE WebSocket
通信模式 单向(服务器向客户端) 双向(全双工通信)
协议 HTTP 独立的 WebSocket 协议
数据格式 纯文本 二进制或文本
自动重连 内置支持 需要手动实现
复杂度 简单,浏览器支持开箱即用 较复杂,需要更多样板代码
使用场景 实时通知、事件流 聊天应用、实时游戏

SSE 通信

Android Client

两种方式:一是只利用 okhttp,二是利用 okhttp-sse。

依赖库

implementation(libs.okhttp)
implementation(libs.okhttp.sse)
okhttp = "4.10.0"
okhttpSse = "4.9.3"

okhttp = { group = "com.squareup.okhttp3", name="okhttp", version.ref = "okhttp" }
okhttp-sse = { group = "com.squareup.okhttp3", name="okhttp-sse", version.ref = "okhttpSse" }

1️⃣ 方式 一:仅用 okhttp

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SSEScreen() {
   
    val sseClient = SSEClient()

    var serverUrl by remember {
    mutableStateOf("http://192.168.3.44:8080/api/sse/stream") }
    var isSubscribed by remember {
    mutableStateOf(false) }
    val messages = remember {
    mutableStateListOf<String>() }

    Scaffold(
        topBar = {
   
            TopAppBar(title = {
    Text("SSE Client") })
        }
    ) {
    padding ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(padding)
                .padding(16.dp)
        ) {
   
            BasicTextField(
                value = serverUrl,
                onValueChange = {
    serverUrl = it },
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(end = 8.dp)
                    .border(1.dp, MaterialTheme.colorScheme.primary, MaterialTheme.shapes.small)
                    .padding(8.dp),
                keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done),
                keyboardActions = KeyboardActions(onDone = {
    /* Handle Enter */ })
            )

            Spacer(Modifier.height(10.dp))

            Button(
                onClick = {
   
                    if (isSubscribed) {
   
                        sseClient.cancel()
                        messages.add("断开连接")
                        isSubscribed = false
                    } else {
   
                      

网站公告

今日签到

点亮在社区的每一天
去签到