Server-Sent Events (SSE) 和 WebSocket 都是用于实现服务器与客户端实时通信的技术,但它们在设计目标、协议特性和适用场景上有显著区别。以下是两者的详细对比:
一、核心区别总结
对比维度SSE (Server-Sent Events)WebSocket通信方向单向(服务器 → 客户端)全双工(服务器 ↔ 客户端)协议基础基于HTTP独立协议(ws:// 或 wss://)数据格式纯文本(事件流格式)二进制或文本自动重连内置支持需手动实现浏览器兼容性除IE外主流浏览器支持所有现代浏览器支持适用场景服务器向客户端推送实时数据(如股票行情、新闻)双向交互场景(如聊天、游戏、协同编辑)二、技术细节对比
1. 连接建立
- SSE:
- // 客户端代码
- const eventSource = new EventSource("/sse-endpoint");
- eventSource.onmessage = (e) => console.log(e.data);
复制代码
- 使用标准HTTP请求,头部包含:
- Accept: text/event-stream
- Cache-Control: no-cache
- Connection: keep-alive
复制代码
- WebSocket:
- // 客户端代码
- const socket = new WebSocket("ws://example.com/ws");
- socket.onmessage = (e) => console.log(e.data);
复制代码
- 通过HTTP Upgrade切换协议:
- GET /ws HTTP/1.1
- Upgrade: websocket
- Connection: Upgrade
复制代码
2. 数据传输
- SSE:
- 服务器响应格式:
- event: priceUpdate
- data: {"symbol":"AAPL","price":182.73}
- \n\n
复制代码 - 支持事件类型(event字段)和重试时间(retry字段)
- WebSocket:
- 二进制或文本帧自由传输:
- // 发送文本
- socket.send("Hello Server!");
- // 发送二进制数据(如文件)
- socket.send(arrayBuffer);
复制代码
3. 连接维护
特性SSEWebSocket心跳检测依赖HTTP长连接需手动实现Ping/Pong帧断线重连自动(客户端默认3秒重试)需手动重连连接状态管理简单(HTTP状态码控制)复杂(需处理多种帧类型)三、选择建议
使用SSE的场景 ✅
- 服务器单向推送
- 实时监控(服务器指标、日志流)
- 新闻/股票行情推送
- 长轮询替代方案
- 需要简单实现
- 无需额外协议,复用HTTP基础设施
- 自动重连和事件ID支持
- 文本数据为主
使用WebSocket的场景 ✅
四、代码示例对比
SSE实现(Spring Boot)
- @GetMapping("/sse")
- public SseEmitter streamData() {
- SseEmitter emitter = new SseEmitter();
- executor.execute(() -> {
- try {
- for (int i = 0; i < 10; i++) {
- emitter.send(
- SseEmitter.event()
- .name("update")
- .data("Event #" + i)
- );
- Thread.sleep(1000);
- }
- emitter.complete();
- } catch (Exception e) {
- emitter.completeWithError(e);
- }
- });
- return emitter;
- }
复制代码 WebSocket实现(Spring Boot)
- @Configuration
- @EnableWebSocket
- public class WebSocketConfig implements WebSocketConfigurer {
- @Override
- public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
- registry.addHandler(myHandler(), "/ws")
- .setAllowedOrigins("*");
- }
- @Bean
- public WebSocketHandler myHandler() {
- return new TextWebSocketHandler() {
- @Override
- protected void handleTextMessage(WebSocketSession session, TextMessage message) {
- // 处理客户端消息
- session.sendMessage(new TextMessage("ECHO: " + message.getPayload()));
- }
- };
- }
- }
复制代码 五、性能与资源消耗
指标SSEWebSocket连接开销较高(HTTP头重复传输)低(连接后无额外开销)服务器内存占用每个连接独立线程/连接更高效的连接管理适合连接数适合中低并发(数千连接)适合高并发(数万连接)六、兼容性解决方案
当需要兼容老旧浏览器时:
- SSE降级方案:使用长轮询(Long Polling)
- WebSocket降级方案:使用SockJS库
- const sock = new SockJS('/ws-endpoint');
- sock.onmessage = (e) => console.log(e.data);
复制代码 总结
- SSE是简单、单向实时通信的理想选择,尤其适合已有HTTP架构的项目。
- WebSocket在需要双向、低延迟交互时不可或缺,但实现复杂度更高。
根据你的应用场景选择:
- 只需接收服务器更新? → 用SSE
- 需要双向对话? → 用WebSocket
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |