SSE和wedsocket的区别

73 阅读4分钟

好的,这是一个非常常见的面试题和技术选型问题。SSE(Server-Sent Events)和 WebSocket 都是用于实现 Web 实时通信的技术,但它们在设计目标、能力和适用场景上有根本的区别。

我们来从多个维度详细对比一下。

核心区别一览表

特性SSE (Server-Sent Events)WebSocket
通信方向单向(仅服务器向客户端推送)双向(全双工,客户端和服务器可以平等地相互发送消息)
协议基于 HTTP独立的 WebSocket 协议 (ws://wss://)
数据格式纯文本,通常是 text/event-stream 格式,有内置格式规范可以传输文本和二进制数据,格式完全自定义
连接建立标准的 HTTP 请求通过 HTTP 升级请求切换到 WebSocket 协议
自动重连内置支持,客户端自动处理需要手动实现
浏览器兼容性除了 IE/Edge (旧版),现代浏览器支持良好几乎所有现代浏览器(包括 IE 10+)
优点简单易用、自动重连、利用现有 HTTP 设施低延迟、全双工、高效、数据格式灵活
缺点只能服务器向客户端推送、最多同时打开 6 个连接(HTTP/1.1限制)需要处理更复杂的协议、需要手动实现重连逻辑

深入解析

1. SSE (Server-Sent Events)

SSE 本质上是一个“长连接”的 HTTP 响应。客户端发起一个普通的 HTTP 请求,服务器保持这个连接打开,并不断地通过这个连接发送数据块。

工作原理:

  1. 客户端使用 EventSource API 向服务器端点发起一个 GET 请求。
  2. 服务器响应头设置为 Content-Type: text/event-stream,并保持连接打开。
  3. 服务器按照特定格式(如 data: This is a message\n\n)周期性地发送数据。
  4. 客户端通过监听 onmessage 事件来接收数据。

关键特点:

  • 单向通信:服务器可以随时向客户端推送数据,但客户端无法通过这个连接向服务器发送数据(除了最初的请求参数)。
  • 自动重连:如果连接意外断开,浏览器会自动尝试重新连接。
  • 轻量级:对于只需要服务器推送的场景,实现起来非常简单。

适用场景:

  • 实时通知:新闻推送、股价更新、社交媒体通知。
  • 实时数据展示:监控仪表盘、实时图表(如 CPU 使用率、在线用户数)。
  • 直播评论、赛事比分更新。

示例代码 (客户端):

const eventSource = new EventSource(‘/api/stream’);

eventSource.onmessage = function(event) {
  const data = JSON.parse(event.data);
  console.log(‘收到消息:’, data);
};

eventSource.onerror = function(error) {
  console.error(‘EventSource 错误:’, error);
};

2. WebSocket

WebSocket 提供了一个真正的全双工通信通道。它在一次 HTTP 握手之后,将连接升级为一个独立的、持久的、双向的 TCP 连接。

工作原理:

  1. 客户端发起一个带有 Upgrade: websocket 头的 HTTP 请求。
  2. 服务器同意升级,返回 101 Switching Protocols 状态码。
  3. 此时,连接不再遵循 HTTP 协议,而是使用 WebSocket 协议 (ws://wss://)。
  4. 此后,客户端和服务器可以随时、独立地向对方发送消息。

关键特点:

  • 双向通信:客户端和服务器是平等的对等体,都可以主动发送消息。
  • 低延迟:由于没有 HTTP 的开销(如每次请求的头部),通信效率更高。
  • 数据格式灵活:可以发送文本,也可以直接发送二进制数据(如图片、文件片段)。

适用场景:

  • 实时交互应用:在线游戏、协同编辑工具(如 Google Docs)。
  • 聊天应用:需要客户端和服务器频繁互发的场景。
  • 金融交易平台、实时定位追踪。

示例代码 (客户端):

const socket = new WebSocket(‘wss://example.com/socket’);

socket.onopen = function(event) {
  console.log(‘连接已建立’);
  socket.send(‘Hello Server!’); // 客户端可以主动发送
};

socket.onmessage = function(event) {
  console.log(‘收到服务器消息:’, event.data);
};

socket.onclose = function(event) {
  console.log(‘连接已关闭’);
};

如何选择?

这是一个简单的决策流程:

  1. 你的应用是否需要客户端频繁地向服务器发送数据?

    • -> 选择 WebSocket
      • 例如:聊天应用(用户频繁发送消息)、实时游戏(玩家不断发送操作指令)。
    • -> 进入第 2 步。
  2. 你的应用主要是服务器向客户端推送更新吗?

    • -> 选择 SSE
      • 例如:实时股价推送、新闻源、服务器状态监控。
    • -> 你可能不需要实时技术,考虑使用轮询或长轮询。

简单总结:

  • SSE 是“增强版的 HTTP 轮询”,它让服务器推送变得简单高效。用它来“订阅”来自服务器的数据流。
  • WebSocket 是“TCP for the Web”,它建立了一个真正的双向通信管道。用它来构建需要高度交互的实时应用。

在实践中,很多场景下两者都能工作,但根据上述原则选择,可以让你用更少的代码获得更好的性能和开发体验。