您现在的位置是:网站首页 > WebSocket实现文章详情
WebSocket实现
陈川
【
Node.js
】
9050人已围观
4170字
WebSocket是一种在单个TCP连接上进行全双工通信的协议,适合需要实时交互的应用场景。Node.js通过ws
等库提供了完整的WebSocket实现能力,从基础连接到高级功能如心跳检测、广播机制均可覆盖。
WebSocket基础概念
WebSocket协议在HTTP握手后升级为持久化连接,与HTTP请求-响应模式不同,它允许服务端主动推送数据。关键特性包括:
- 低延迟:建立连接后数据传输无需重复握手
- 双向通信:客户端和服务端可同时发送消息
- 轻量级:数据帧头仅2-10字节
协议标识符为ws
(非加密)或wss
(SSL加密),握手阶段通过HTTP头完成:
GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Node.js服务端实现
使用ws库搭建服务
安装基础依赖:
npm install ws
创建基础服务端:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
console.log('新客户端连接');
ws.on('message', (message) => {
console.log(`收到消息: ${message}`);
ws.send(`服务器回应: ${message}`);
});
ws.on('close', () => {
console.log('客户端断开连接');
});
});
连接生命周期管理
典型事件处理流程:
wss.on('connection', (ws) => {
// 标识客户端
ws.id = generateUUID();
// 错误处理
ws.on('error', (error) => {
console.error(`客户端 ${ws.id} 错误:`, error);
});
// 心跳检测
const heartbeat = () => {
ws.isAlive = true;
};
const interval = setInterval(() => {
if (!ws.isAlive) return ws.terminate();
ws.isAlive = false;
ws.ping();
}, 30000);
ws.on('pong', heartbeat);
});
客户端实现示例
浏览器端基础连接:
const socket = new WebSocket('ws://localhost:8080');
socket.addEventListener('open', (event) => {
socket.send('Hello Server!');
});
socket.addEventListener('message', (event) => {
console.log('来自服务端的消息:', event.data);
});
// 重连机制
function reconnect() {
setTimeout(() => {
new WebSocket(socket.url);
}, 5000);
}
高级功能实现
广播消息实现
向所有客户端广播消息:
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'broadcast',
data: '系统公告'
}));
}
});
房间分组管理
const rooms = {};
wss.on('connection', (ws) => {
ws.on('join', (roomId) => {
if (!rooms[roomId]) rooms[roomId] = new Set();
rooms[roomId].add(ws);
});
ws.on('leave', (roomId) => {
rooms[roomId]?.delete(ws);
});
});
function broadcastToRoom(roomId, message) {
rooms[roomId]?.forEach(client => {
client.send(message);
});
}
性能优化实践
消息压缩配置
启用permessage-deflate扩展:
const wss = new WebSocket.Server({
port: 8080,
perMessageDeflate: {
zlibDeflateOptions: {
chunkSize: 1024,
memLevel: 7,
level: 3
},
threshold: 1024 // 仅大于1KB的消息压缩
}
});
连接数限制
防止DDoS攻击:
const wss = new WebSocket.Server({
maxPayload: 1024 * 1024, // 1MB
verifyClient: (info, cb) => {
const isValid = info.origin === 'https://trusted-domain.com';
cb(isValid);
}
});
安全防护措施
TLS加密配置
const fs = require('fs');
const server = require('https').createServer({
cert: fs.readFileSync('server.crt'),
key: fs.readFileSync('server.key')
});
const wss = new WebSocket.Server({ server });
server.listen(443);
消息验证模式
ws.on('message', (rawData) => {
try {
const data = JSON.parse(rawData);
if (!validateSchema(data)) {
throw new Error('非法消息格式');
}
processMessage(data);
} catch (err) {
ws.terminate();
}
});
调试与问题排查
连接状态监控
setInterval(() => {
console.log(`当前连接数: ${wss.clients.size}`);
console.log(`内存使用: ${process.memoryUsage().rss / 1024 / 1024}MB`);
}, 5000);
错误日志记录
wss.on('error', (err) => {
fs.appendFileSync('websocket.log',
`${new Date().toISOString()} - ${err.stack}\n`
);
});
实际应用场景
实时协作编辑器
操作同步实现片段:
// 客户端发送编辑操作
socket.send(JSON.stringify({
type: 'text-update',
position: 42,
text: '新增内容'
}));
// 服务端处理
ws.on('message', (msg) => {
const operation = JSON.parse(msg);
broadcastToRoom(operation.docId, msg);
});
在线游戏状态同步
// 玩家位置更新
setInterval(() => {
const players = Array.from(wss.clients)
.map(client => client.playerData);
wss.clients.forEach(client => {
client.send(JSON.stringify({
type: 'game-state',
players
}));
});
}, 100);