WebSocket 和 SSE 简单使用及区别

文章目录

  • [WebSocket 和 SSE 简单使用及区别](#WebSocket 和 SSE 简单使用及区别)
    • [1. SSE 是什么](#1. SSE 是什么)
    • [2. Spring Boot 中使用 SSE](#2. Spring Boot 中使用 SSE)
    • [3. SSE 适合哪些场景](#3. SSE 适合哪些场景)
    • [4. WebSocket 是什么](#4. WebSocket 是什么)
    • [5. Spring Boot 中使用 WebSocket](#5. Spring Boot 中使用 WebSocket)
    • [6. WebSocket 适合哪些场景](#6. WebSocket 适合哪些场景)
    • [7. WebSocket 和 SSE 的区别](#7. WebSocket 和 SSE 的区别)
    • [8. 怎么选择](#8. 怎么选择)
    • [9. 和 AI 流式输出的关系](#9. 和 AI 流式输出的关系)
    • [10. 总结](#10. 总结)

WebSocket 和 SSE 简单使用及区别

在 Web 开发中,HTTP 请求通常是"一问一答":客户端发起请求,服务端返回响应,请求就结束了。

但有些场景需要服务端主动把数据推给客户端,例如:

  • AI 流式回答
  • 消息通知
  • 聊天室
  • 实时日志
  • 订单状态变化
  • 大屏数据刷新

这类场景常见的方案有两个:WebSocket 和 SSE。

1. SSE 是什么

SSE 全称是 Server-Sent Events,意思是服务端发送事件。

它的特点是:客户端通过 HTTP 建立连接,服务端可以持续向客户端推送文本数据。

SSE 是单向通信:

text 复制代码
客户端  ----建立连接---->  服务端
客户端  <---持续推送----  服务端

也就是说,SSE 主要适合"服务端不断推消息给客户端"的场景。

2. Spring Boot 中使用 SSE

Spring MVC 中可以使用 SseEmitter 实现 SSE。

java 复制代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

@RestController
public class SseController {

    @GetMapping("/sse")
    public SseEmitter sse() {
        SseEmitter emitter = new SseEmitter(0L);

        new Thread(() -> {
            try {
                for (int i = 1; i <= 5; i++) {
                    emitter.send("第 " + i + " 条消息");
                    Thread.sleep(1000);
                }
                emitter.complete();
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        }).start();

        return emitter;
    }
}

前端可以这样接收:

html 复制代码
<!DOCTYPE html>
<html>
<body>
<div id="message"></div>

<script>
  const eventSource = new EventSource("/sse");

  eventSource.onmessage = function (event) {
    const div = document.getElementById("message");
    div.innerHTML += `<p>${event.data}</p>`;
  };

  eventSource.onerror = function () {
    eventSource.close();
  };
</script>
</body>
</html>

访问页面后,服务端会每隔一秒推送一条消息。

3. SSE 适合哪些场景

SSE 适合服务端向客户端单向推送数据:

  • AI 流式输出
  • 系统通知
  • 实时日志
  • 股票行情
  • 订单状态推送
  • 后台任务进度

比如 Spring AI 的流式输出,本质上就很适合配合 SSE 使用。服务端一边从大模型拿到生成内容,一边推给浏览器。

4. WebSocket 是什么

WebSocket 是一种双向通信协议。

建立连接后,客户端和服务端都可以主动给对方发消息。

text 复制代码
客户端  <----双向通信---->  服务端

WebSocket 更像是一条长期存在的通信通道,适合实时互动场景。

5. Spring Boot 中使用 WebSocket

先定义 WebSocket 处理器:

java 复制代码
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

@Component
public class MyWebSocketHandler extends TextWebSocketHandler {

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        session.sendMessage(new TextMessage("服务端收到:" + payload));
    }
}

再配置 WebSocket 路径:

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    private final MyWebSocketHandler myWebSocketHandler;

    public WebSocketConfig(MyWebSocketHandler myWebSocketHandler) {
        this.myWebSocketHandler = myWebSocketHandler;
    }

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myWebSocketHandler, "/ws")
                .setAllowedOrigins("*");
    }
}

前端连接 WebSocket:

html 复制代码
<!DOCTYPE html>
<html>
<body>
<input id="text" placeholder="请输入消息">
<button onclick="send()">发送</button>
<div id="message"></div>

<script>
  const socket = new WebSocket("ws://localhost:8080/ws");

  socket.onmessage = function (event) {
    const div = document.getElementById("message");
    div.innerHTML += `<p>${event.data}</p>`;
  };

  function send() {
    const input = document.getElementById("text");
    socket.send(input.value);
    input.value = "";
  }
</script>
</body>
</html>

这样客户端可以主动发送消息给服务端,服务端也可以主动返回消息。

6. WebSocket 适合哪些场景

WebSocket 适合双向实时通信:

  • 在线聊天室
  • 在线客服
  • 多人协作编辑
  • 实时游戏
  • 实时控制台
  • 需要客户端和服务端频繁互发消息的业务

如果业务只是服务端推送进度或模型输出,用 SSE 更简单。如果业务需要用户和服务端实时互发消息,用 WebSocket 更合适。

7. WebSocket 和 SSE 的区别

对比项 SSE WebSocket
通信方向 服务端到客户端,单向推送 客户端和服务端双向通信
协议 基于 HTTP 独立的 WebSocket 协议
前端 API EventSource WebSocket
数据格式 主要是文本 文本和二进制都可以
自动重连 浏览器原生支持 需要自己实现
使用复杂度 较简单 相对复杂
适合场景 通知、日志、进度、AI 流式输出 聊天、协作、游戏、实时交互
浏览器支持 主流浏览器支持 主流浏览器支持

8. 怎么选择

如果只是服务端持续推送数据,优先考虑 SSE。

例如:

text 复制代码
服务端生成内容 -> 浏览器实时展示

这类场景使用 SSE 更简单。

如果客户端和服务端都需要频繁主动发送消息,选择 WebSocket。

例如:

text 复制代码
用户发送消息 -> 服务端处理 -> 服务端推送给其他用户

这类场景 WebSocket 更合适。

简单总结:

text 复制代码
只需要服务端推客户端:SSE
需要客户端和服务端双向通信:WebSocket

9. 和 AI 流式输出的关系

在 AI 应用中,用户输入一个问题后,大模型通常会一点一点生成内容。

这时常见流程是:

text 复制代码
用户提问
  ↓
后端调用大模型 stream 接口
  ↓
后端收到一段内容
  ↓
通过 SSE 推给前端
  ↓
前端逐字或逐段展示

如果使用 Spring AI,后端可能会返回 Flux<String>:

java 复制代码
@GetMapping(value = "/ai/stream", produces = "text/html;charset=UTF-8")
public Flux<String> stream(String msg) {
    return chatClient.prompt()
            .user(msg)
            .stream()
            .content();
}

这种写法就非常适合配合前端流式展示。

如果是完整的 AI 聊天室,而且需要用户在线状态、多人消息广播、主动取消生成、服务端主动控制会话等复杂能力,可以考虑 WebSocket。

10. 总结

SSE 和 WebSocket 都可以实现实时通信,但定位不一样。

SSE 更轻量,适合服务端单向推送,例如通知、进度、日志、AI 流式输出。

WebSocket 更灵活,适合双向通信,例如聊天室、在线客服、协作编辑、实时游戏。

实际开发中,不需要一上来就用最复杂的方案。能用普通 HTTP 解决就用 HTTP;需要服务端推送就考虑 SSE;需要双向实时通信再使用 WebSocket。

相关推荐
承渊政道1 天前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
爱和冰阔落1 天前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
严肃小白兔1 天前
Cloudflare 更新 API Token 管理:从最小权限到自动化凭据安全
网络·安全·自动化
Linux-lucky2 天前
45-Linux学习之旅之防火墙与WEB加固
linux·前端·网络·学习·ubuntu
博客zhu虎康2 天前
实现局域网P2P通信:内网发送消息
网络·网络协议·p2p
吴声子夜歌2 天前
Kubernetes权威指南——网络原理(一)
网络·容器·kubernetes
陈希1232 天前
Linux 服务器性能排查手册(2026):CPU、内存、磁盘IO、网络四大瓶颈定位
linux·服务器·网络
国科安芯2 天前
从遥控到自治:ASP4644S2B支撑星载电源健康管理与容错配电
网络·单片机·嵌入式硬件·安全·dcdc·低轨卫星·商业航天
|_⊙2 天前
网络层协议 IP
服务器·网络·tcp/ip
无言听风雨丶2 天前
Kubernetes Service Mesh 与 mTLS 实战:从网络可达走向零信任服务通信
网络·kubernetes·service_mesh