WebSocket
WebSocket提供全双工通信通道,允许服务器主动向客户端推送数据,适用于实时应用。
WebSocket优势
实时通信
服务器可主动推送数据到客户端
低延迟
持久连接,无需重复建立连接
双向通信
客户端和服务器可随时互相发送数据
高效传输
相比HTTP请求,开销更小
协议对比
| 协议 | 方向 | 实时性 | 复杂度 | 适用场景 |
|---|---|---|---|---|
| SSE | 单向(服务器→客户端) | 高 | 低 | 实时通知、股票价格、日志流 |
| WebSocket | 双向 | 极高 | 高 | 聊天应用、在线游戏、协作工具 |
| Ajax轮询 | 双向 | 低 | 低 | 简单数据更新、兼容性要求高 |
| 长轮询 | 双向 | 中等 | 中等 | 实时应用、但需要兼容低版本浏览器 |
连接握手过程
WebSocket连接通过HTTP协议进行握手,然后升级为WebSocket协议:
// 客户端请求
GET /ws HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
// 服务器响应
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
实现示例
// WebSocket客户端示例
class WebSocketClient {
constructor(url) {
this.url = url;
this.ws = null;
this.connect();
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = event => {
console.log('WebSocket连接已建立');
// 发送认证信息
this.send({type: 'auth', token: localStorage.getItem('token')});
};
this.ws.onmessage = event => {
const data = JSON.parse(event.data);
this.handleMessage(data);
};
this.ws.onclose = event => {
console.log('WebSocket连接已关闭');
// 尝试重连
setTimeout(() => this.connect(), 5000);
};
this.ws.onerror = error => {
console.error('WebSocket错误:', error);
};
}
send(data) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
}
}
handleMessage(data) {
switch (data.type) {
case 'message':
// 处理消息
console.log('收到消息:', data.content);
break;
case 'notification':
// 处理通知
showNotification(data.message);
break;
case 'userUpdate':
// 处理用户更新
updateUserInterface(data.user);
break;
default:
console.warn('未知消息类型:', data.type);
}
}
}
// 使用示例
const client = new WebSocketClient('ws://localhost:8080/ws');
// 发送消息
client.send({type: 'message', content: 'Hello, world!'});
// 服务器端实现示例 (Node.js/ws)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
console.log('新客户端连接');
ws.on('message', (message) => {
const data = JSON.parse(message);
// 处理不同类型的消息
switch (data.type) {
case 'message':
// 广播消息给所有连接的客户端
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'message',
content: data.content,
timestamp: Date.now()
}));
}
});
break;
case 'auth':
// 处理认证
if (validateToken(data.token)) {
ws.authenticated = true;
ws.send(JSON.stringify({type: 'authSuccess'}));
} else {
ws.send(JSON.stringify({type: 'authFailed'}));
ws.close();
}
break;
default:
console.warn('未知消息类型:', data.type);
}
});
ws.on('close', () => {
console.log('客户端断开连接');
});
ws.on('error', (error) => {
console.error('WebSocket错误:', error);
});
});
使用场景
实时聊天
即时通讯、在线客服等
多人协作
文档协同编辑、白板协作等
在线游戏
多人游戏、实时对战等
实时监控
系统监控、数据可视化等
安全考虑
认证与授权
在连接建立后验证用户身份,确保只有授权用户能进行通信
跨站WebSocket攻击
验证Origin头,防止恶意网站利用用户身份建立WebSocket连接
消息验证
验证客户端发送的消息格式和内容,防止注入攻击
连接限制
限制单个IP的连接数,防止WebSocket洪水攻击
最佳实践
- 实现心跳机制检测连接状态
- 处理连接断开和重连逻辑
- 使用二进制数据传输提高效率
- 实现消息确认和重发机制
- 考虑使用WebSocket库如Socket.io提供额外功能
- 使用WSS(WebSocket Secure)加密传输数据
- 对传输的数据进行适当的序列化和验证