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 流式回答
  • 消息通知
  • 聊天室
  • 实时日志
  • 订单状态变化
  • 大屏数据刷新

这类场景常见的方案有两个:WebSocketSSE

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。

相关推荐
weixin_462901971 小时前
TCP+WebSocket双向转发服务器 完整部署运维手册
运维·websocket·tcp/ip
编程牛马姐1 小时前
什么是纯净IP? 如何判断IP地址的纯净度?有哪些干净IP推荐?
网络
Sirius Wu2 小时前
OpenClaw Model Provider(模型提供商)完整详解
服务器·网络·人工智能·安全·aigc
RD_daoyi2 小时前
Google偷偷给AI引用加了五个新功能:内联引用、悬停预览、品牌展示……但点击率真的回来了吗?
大数据·网络·人工智能·算法·安全·搜索引擎
tiantianuser2 小时前
NVME-oF IP 设计11 : 控制面与数据面干什么用?
网络协议·rdma·高速传输·roce v2·nvme of
ShineWinsu3 小时前
对于Linux:自定义协议(基于TCP)实现网络计算器的解析
linux·网络·c++·网络协议·tcp/ip·面试·网络计算器
q567315233 小时前
Scrapy 框架集成稳定 HTTP 代理:中间件配置与断线重试实战
爬虫·网络协议·scrapy·http·中间件·http代理
完美火龙篇 四月的友4 小时前
SpringBoot 即时聊天 IM 完整实现(HTTP会话管理 \+ WebSocket实时推送 \+ 离线消息)
spring boot·websocket·http
ANSIOT4 小时前
蓝牙两轮车智能仪表方案:手机互联,一屏掌控
网络·科技·物联网