WebSocket 是一种基于 TCP 的应用层全双工通信协议 ,2011 年被 IETF 标准化为 RFC 6455,旨在解决 HTTP 单向通信的局限性,实现服务器与客户端之间的低延迟、实时双向数据传输。
一、核心定义与背景
- 定义:WebSocket 允许在单个 TCP 连接上进行双向、全双工通信,客户端和服务器完成一次握手后即可建立持久连接,双方可随时主动发送数据
- 诞生背景 :
- 传统 HTTP 采用 "请求 - 响应" 模式,服务器无法主动推送数据
- 轮询 / 长轮询方案存在高延迟、资源浪费、频繁连接等问题
- WebSocket 通过协议升级机制,在 HTTP 基础上建立持久双向通道
二、核心特性
| 特性 | 说明 |
|---|---|
| 全双工通信 | 客户端和服务器可同时发送和接收数据,突破 HTTP 单向限制 |
| 持久连接 | 一次握手建立连接,长期保持,减少连接开销 |
| 低开销 | 帧头最小仅 2 字节,比 HTTP 请求头 (数百字节) 高效得多 |
| 实时性高 | 数据可即时传输,延迟可达毫秒级,适合实时场景 |
| 兼容性好 | 使用 80/443 端口,握手阶段通过 HTTP,兼容现有网络设施 |
| 安全性 | 支持 wss://(基于 TLS/SSL) 加密传输,保障数据安全 |
| 原生跨域 | 支持跨域通信,通过服务器配置即可实现 |
三、工作原理
1. 连接建立(握手过程)
WebSocket 通过 HTTP/1.1 的Upgrade 机制完成协议升级:
客户端请求 → 服务器响应 → 协议升级完成
-
客户端握手请求(关键头字段):
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket # 核心:请求升级到WebSocket Connection: Upgrade # 配合Upgrade字段 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== # 随机密钥,用于验证 Sec-WebSocket-Version: 13 # 协议版本,必须是13 -
服务器握手响应(关键头字段):
HTTP/1.1 101 Switching Protocols # 状态码表示协议切换成功 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= # 密钥验证结果验证逻辑:服务器将
Sec-WebSocket-Key+ 固定 GUID (258EAFA5-E914-47DA-95CA-C5AB0DC85B11),进行 SHA-1 哈希并 Base64 编码,得到Sec-WebSocket-Accept值
2. 数据传输
连接建立后,数据以帧 (Frame) 为单位传输,帧结构如下:
| 字段 | 长度 | 说明 |
|---|---|---|
| FIN | 1 位 | 1 表示是消息最后一帧,0 表示后续还有帧 |
| RSV1-3 | 3 位 | 扩展位,通常为 0 |
| Opcode | 4 位 | 帧类型:0x1 (文本)、0x2 (二进制)、0x8 (关闭)、0x9 (Ping)、0xA (Pong) 等 |
| Mask | 1 位 | 1 表示数据被掩码处理 (客户端发送必须置 1) |
| Payload len | 7/7+16/7+64 位 | 数据长度:0-125 (直接表示),126 (后续 2 字节),127 (后续 8 字节) |
| Masking-key | 0/4 字节 | 掩码密钥 (仅客户端发送有) |
| Payload data | 可变 | 实际传输的数据 |
3. 连接维护与关闭
- 心跳机制:通过 Ping/Pong 帧检测连接状态,一方发送 Ping,另一方必须回复 Pong
- 关闭过程 :
- 一方发送 Opcode=0x8 的关闭帧,包含关闭码和原因
- 另一方返回确认关闭帧
- 双方关闭 TCP 连接
四、WebSocket vs HTTP 核心区别
| 对比维度 | WebSocket | HTTP/1.x |
|---|---|---|
| 通信模式 | 双向全双工,服务器可主动推送 | 单向请求 - 响应,客户端主导 |
| 连接状态 | 持久连接,一次握手长期有效 | 无状态,每次请求独立,默认短连接 |
| 数据格式 | 帧格式,头开销小 (2-14 字节) | 文本格式,头开销大 (数百字节) |
| 实时性 | 高 (毫秒级),数据即时传输 | 低 (秒级),依赖轮询 / 长轮询 |
| 适用场景 | 实时聊天、监控、协作工具、游戏等 | 页面加载、资源获取、表单提交等 |
| 协议标识 | ws://(非加密)、wss://(加密) | http://、https:// |
五、典型应用场景
- 即时通讯:在线聊天、客服系统、社交消息推送
- 实时数据展示:股票行情、体育赛事直播、监控仪表盘
- 协作工具:多人在线编辑、白板共享、远程协作
- 游戏:多人在线游戏的实时交互
- 物联网:设备状态实时上报与控制
- 通知系统:系统告警、订单状态更新推送
六、Java 实现示例(Spring Boot)
以下是一个简单的 WebSocket 聊天服务器实现,基于 Spring Boot 的 WebSocket 支持:
// 1. 配置类
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 注册处理器,允许跨域
registry.addHandler(chatHandler(), "/chat")
.setAllowedOrigins("*")
.withSockJS(); // 降级支持,兼容不支持WebSocket的浏览器
}
@Bean
public WebSocketHandler chatHandler() {
return new ChatWebSocketHandler();
}
}
// 2. 处理器类
public class ChatWebSocketHandler extends TextWebSocketHandler {
// 存储所有连接的会话
private static final Set<WebSocketSession> sessions =
Collections.synchronizedSet(new HashSet<>());
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
sessions.add(session);
System.out.println("新连接:" + session.getId());
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
System.out.println("收到消息:" + payload);
// 广播消息给所有连接
for (WebSocketSession s : sessions) {
if (s.isOpen()) {
s.sendMessage(new TextMessage("用户[" + session.getId() + "]: " + payload));
}
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
sessions.remove(session);
System.out.println("连接关闭:" + session.getId());
}
}
// 3. 前端测试代码
// <script>
// const socket = new WebSocket('ws://localhost:8080/chat');
// socket.onopen = () => console.log('连接成功');
// socket.onmessage = (event) => console.log('收到消息:', event.data);
// socket.send('Hello WebSocket!');
// </script>
七、面试速记版(核心考点)
- WebSocket 定义:基于 TCP 的全双工通信协议,通过 HTTP 握手升级建立持久连接,实现服务器主动推送
- 核心优势:全双工、低延迟、低开销、持久连接,解决 HTTP 实时性不足问题
- 握手过程:客户端发送 Upgrade 请求→服务器返回 101 状态码→协议升级完成
- 帧结构:FIN、RSV、Opcode、Mask、Payload len、Masking-key、Payload data
- 状态码:1000 (正常关闭)、1001 (离开)、1002 (协议错误)、1003 (数据类型错误) 等
- 与 HTTP 区别:双向 vs 单向、持久 vs 短连接、低延迟 vs 高延迟、帧 vs 请求 - 响应
- 应用场景:实时聊天、监控、游戏、协作工具等需要双向实时通信的场景
- 安全:使用 wss:// 加密,避免数据被窃听
- 心跳机制:Ping/Pong 帧维持连接,检测异常断开
- Java 实现:Spring Boot 通过 @EnableWebSocket 和 WebSocketHandler 实现,支持 SockJS 降级