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。

相关推荐
x_x-F5 小时前
网络数据从网卡到用户态:一场基于内存所有权转移的接力赛
开发语言·网络·php
mitugaoyang199310 小时前
marvell88Q5152交换机开发(0)-芯片介绍
网络
CDN36010 小时前
流媒体加速实践:出海东南亚短视频点播频繁缓冲,HLS 分片与 Nginx 配置调优
java·网络·nginx·流媒体加速
xiaoxiangsiyan10 小时前
RHCE2026完整版全知识点清单
运维·网络·学习·自动化·rhce
AlanBruce11 小时前
摩尔信使MThings新功能:水电不分家、一键设备扫描
网络·自动化·plc·mthings·摩尔信使·电气·西门子s7
Titan202411 小时前
Linux网络基础知识
linux·服务器·网络·c++·学习
RisunJan12 小时前
Linux命令-tcpdump(网络数据包捕获)
linux·网络·tcpdump
Titan202412 小时前
Linux网络学习:套接字、UDP的封装与应用
linux·服务器·开发语言·网络·c++
啦啦啦啦啦zzzz15 小时前
TCP协议详解
网络·网络协议·tcp/ip
jason.zeng@150220715 小时前
服务器磁盘读写效率,网络吞吐量查看,mysql性能调优
服务器·网络·mysql