传统的 HTTP 协议是"请求-响应"模型:浏览器不询问,服务器不回答。这对于实时更新(如聊天、实时通知、股票行情)来说效率极低,因为浏览器不知道服务器何时有新数据。
这四种技术都是为了打破这个限制而生的。
- WebSocket - 全双工通信通道
WebSocket 是 HTML5 引入的一种全新协议(ws:// 或 wss://),它和 HTTP 是并列的协议。它的目标是在单个 TCP 连接上提供全双工的通信。
工作原理:
- 握手: 客户端首先发送一个特殊的 HTTP 请求(带有 Upgrade: websocket 头),请求将连接升级为 WebSocket 协议。
- 升级协议: 服务器同意升级后(返回 101 状态码),当前的 HTTP 连接就被"劫持"了,转变为 WebSocket 连接。
- 全双工通信: 此后,服务器和客户端可以随时、主动地向对方发送数据,不再需要请求-响应模式。这个连接会一直保持。
特点:
• 真正的实时: 服务器可以主动推送数据,延迟极低。
• 高效: 建立连接后,通信开销很小(数据包头很小)。
• 全双工: 客户端和服务器可以同时发送数据。
• 长连接: 一个连接持续存在,避免了频繁建立连接的开销。
适用场景:
• 在线聊天室
• 多人在线游戏
• 协同编辑工具(如 Google Docs)
• 实时体育/金融数据更新
javascript
// 客户端 JavaScript
const socket = new WebSocket('wss://echo.websocket.org');
// 连接开启
socket.onopen = function(event) {
socket.send('Hello Server!');
};
// 接收服务器消息
socket.onmessage = function(event) {
console.log('Message from server:', event.data);
};
// 连接关闭
socket.onclose = function(event) {
console.log('Connection closed');
};
- SSE - 服务器发送事件
SSE 是一种允许服务器单向向客户端推送数据的 HTML5 技术。它基于标准的 HTTP 协议,因此更容易被现有网络设施接受。
工作原理:
- 客户端通过一个普通的 HTTP 请求连接到服务器。
- 服务器保持这个连接打开,并设置响应头 Content-Type: text/event-stream。
- 在连接持续期间,服务器可以随时通过这个连接发送一段遵循特定格式(以 data: 开头)的文本数据给客户端。
特点:
• 单向通信: 只能从服务器推送到客户端。客户端要向服务器发送数据,需要另外使用 AJAX 等技术。
• 基于 HTTP: 无需额外协议,兼容性好,更容易实现。
• 自动重连: 协议内置了重连机制。
• 纯文本: 通常用于传输文本数据(如 JSON)。
适用场景:
• 实时通知(新闻推送、价格提醒)
• 社交媒体动态更新
• 监控仪表盘(服务器状态、日志流)
代码示例:
javascript
// 客户端 JavaScript
const eventSource = new EventSource('/api/stream');
// 监听通用消息
eventSource.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log('New update:', data);
};
// 监听自定义事件类型
eventSource.addEventListener('userConnected', function(event) {
console.log('A user connected:', event.data);
});
// 错误处理(会自动重连)
eventSource.onerror = function(event) {
console.error('EventSource failed.');
};
服务器响应格式:
javascript
```javascript
event: userConnected
data: {"userId": 123, "name": "John"}
data: This is a message
data: with multiple lines.
- 长轮询 - "聪明的"轮询
长轮询是对传统轮询的一种优化,试图模拟服务器推送。
工作原理:
-
客户端向服务器发送一个请求。
-
服务器收到请求后,不会立即响应,而是将这个请求挂起。
-
直到以下两种情况之一发生,服务器才返回响应:
◦ 服务器有新数据: 立即返回数据。
◦ 请求超时: 达到一个设定的超时时间(如 30 秒)后,返回一个空响应。
-
客户端收到响应(无论有无数据)后,立即发起一个新的请求,重复步骤 1。这样就维持了一个持续的连接。
特点:
• 实时性较好: 相比短轮询,能更快地拿到数据。
• 兼容性极佳: 使用最基本的 HTTP 请求,任何浏览器都支持。
• 服务器资源消耗: 比短轮询少,但仍有大量请求,并且服务器需要保持连接挂起。
适用场景:
• 老式浏览器的实时通信方案。
• WebSocket 和 SSE 不可用时的备选方案。
- 短轮询 - "笨拙的"轮询
这是最简单粗暴的方式。
工作原理:
客户端以固定的时间间隔(例如每 5 秒)向服务器发送 HTTP 请求,询问"有新数据吗?"。服务器每次都会立即响应,无论有没有新数据("有数据"或"没有")。
特点:
• 实现简单
• 实时性差: 延迟取决于轮询间隔。
• 浪费资源: 即使没有新数据,也会产生大量无效的请求和响应,对服务器和网络都是负担。
适用场景:
• 对实时性要求不高的数据更新,例如每分钟检查一次版本更新。
• 基本已被长轮询、SSE 和 WebSocket 取代。
总结与对比
技术 通信方向 协议 优点 缺点 适用场景
WebSocket 全双工 ws, wss (基于 TCP) 真正实时,高效,低延迟 需要服务器端特殊支持,协议更复杂 高交互应用(聊天、游戏)
SSE 服务器->客户端 HTTP 真正实时(服务端推送),自动重连,基于 HTTP 简单 只能服务器向客户端推送 实时通知、数据流监控
长轮询 双向(通过多个请求) HTTP 实时性较好,兼容性极佳 仍有请求延迟,服务器需保持连接 兼容性要求高的备选方案
短轮询 双向(通过多个请求) HTTP 实现极其简单 实时性差,资源浪费严重 基本淘汰,仅用于非实时检查
如何选择?
-
需要极高的实时性和双向通信(如聊天、游戏)?
◦ 选择 WebSocket。
-
只需要服务器向客户端推送数据(如新闻推送、监控)?
◦ 选择 SSE。 它更简单,并且基于 HTTP,优势明显。
-
需要支持非常老的浏览器,且 WebSocket/SSE 不可用?
◦ 选择长轮询 作为降级方案。
-
对实时性要求极低(如每分钟检查一次)?
◦ 可以考虑简单的短轮询,但长轮询通常仍是更好的选择。