什么是 WebSocket?
WebSocket 是一种 全双工通信协议,用于在客户端(如浏览器)和服务器之间建立持久连接。通过 HTTP 协议升级为 WebSocket 协议后,可以实现实时、双向通信,适用于需要高频数据交互的场景,如即时消息、实时通知、在线游戏等。
WebSocket 的特点
-
全双工通信
- 客户端和服务器都可以随时发送和接收消息。
- 不像 HTTP 那样每次通信都需要请求和响应。
-
持久连接
- 一旦连接建立,客户端和服务器之间的通信无需频繁重新建立连接。
- 减少了传统 HTTP 请求的开销。
-
实时性
- 数据可以立即推送到对方,而不需要等待请求。
- 适合对延迟敏感的场景。
-
轻量协议
- WebSocket 的帧头较小,只有 2-14 字节(相比 HTTP 的大量请求头更轻量)。
WebSocket 的工作原理
1. 握手阶段
WebSocket 连接从标准的 HTTP 请求开始,通过一个特殊的 HTTP 请求将协议从 HTTP 升级为 WebSocket。
- 客户端发送 HTTP 请求:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
-
Upgrade: websocket
和Connection: Upgrade
表示请求协议升级为 WebSocket。 -
Sec-WebSocket-Key
是随机生成的字符串,用于服务器验证。 -
服务器返回响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
- 状态码
101 Switching Protocols
表示协议升级成功。 Sec-WebSocket-Accept
是服务器根据Sec-WebSocket-Key
计算的值,用于确认握手的有效性。
2. 数据传输阶段
握手成功后,连接切换到 WebSocket 协议,客户端和服务器可以直接通过 帧(frame) 进行双向通信。
- 数据帧结构简单,通常包含:
- 帧头:表示数据类型(如文本、二进制)。
- 有效载荷:实际的数据。
3. 关闭阶段
- WebSocket 连接可以由客户端或服务器主动关闭。
- 双方通过发送
Close
帧结束连接。
WebSocket 的优势
- 效率高
- 持久连接避免了传统 HTTP 的频繁请求和响应。
- 帧头开销小,比 HTTP 请求更加轻量。
- 实时性强
- 数据可以即时双向传输,适合实时通信场景。
- 服务器推送
- 服务器可以主动向客户端推送数据,而无需等待客户端请求。
WebSocket 与 HTTP 的比较
特性 | WebSocket | HTTP |
---|---|---|
连接模式 | 持久连接(双向通信) | 请求-响应(单向通信) |
开销 | 一次握手后,后续通信开销小 | 每次请求都需要头部,开销大 |
数据方向 | 客户端与服务器均可主动发送和接收数据 | 客户端发起请求,服务器响应数据 |
适用场景 | 实时通信、频繁消息交互 | 静态页面、一次性请求 |
WebSocket 的典型应用场景
- 即时消息
- 如聊天应用(WhatsApp、Slack)。
- 客户端和服务器可以实时收发消息。
- 实时通知
- 如股票价格、新闻推送、体育赛事更新。
- 在线协作
- 文档协作工具(Google Docs)或在线白板。
- 实时数据流
- 如在线游戏、多媒体流(音视频通话)、传感器数据监控。
- 物联网(IoT)
- 设备和服务器之间的低延迟通信。
WebSocket 示例代码
1. 客户端实现(JavaScript)
// 创建 WebSocket 连接
const socket = new WebSocket('ws://example.com/socket');
// 连接成功
socket.onopen = function(event) {
console.log("WebSocket is open now.");
socket.send("Hello Server!"); // 发送数据
};
// 接收消息
socket.onmessage = function(event) {
console.log("Message from server:", event.data);
};
// 连接关闭
socket.onclose = function(event) {
console.log("WebSocket is closed now.");
};
// 发生错误
socket.onerror = function(error) {
console.error("WebSocket error observed:", error);
};
2. 服务器实现(Python 示例:使用 websockets 库)
``` python
import asyncio
import websockets
async def handler(websocket, path):
async for message in websocket:
print(f"Message from client: {message}")
await websocket.send(f"Echo: {message}")
# 启动 WebSocket 服务器
start_server = websockets.serve(handler, "localhost", 6789)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
运行后,客户端连接到 ws://localhost:6789,可以与服务器实时通信。
WebSocket 与其他技术对比
- 与 HTTP/2
- HTTP/2 支持多路复用,但仍是请求-响应模式。
- WebSocket 更适合实时、双向通信。
- 与 WebRTC
- WebRTC 专注于点对点音视频流传输,包含更复杂的协议栈。
- WebSocket 更通用,适用于广泛的实时数据传输场景。
- 与轮询/长轮询
- 轮询通过频繁发起 HTTP 请求获取数据,效率较低。
- WebSocket 持久连接,避免了重复的请求开销。
总结
WebSocket 是一种高效的实时通信协议,适合需要频繁双向数据交互的应用场景。它克服了传统 HTTP 的局限性,通过轻量的持久连接,为现代 Web 应用程序提供了可靠的实时通信能力。