关于 websocket-implementation
面向构建实时应用的开发者,提供 WebSocket 服务端与客户端实现指导,涵盖 Socket.IO、React 集成、扩展和运行监控。
主要功能
- 01Socket.IO 服务端与客户端模式
- 02React WebSocket Hook 示例
- 03消息协议设计
- 04基于 Redis 的扩展建议
- 05连接监控端点
适用场景
- 01构建实时消息功能
- 02管理经过身份验证的 WebSocket 连接
- 03使用 Redis 扩展部署
- 04跟踪活跃连接与房间
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill websocket-implementation安装后在 Claude Code 中输入/websocket-implementation确认已加载。
附带文件references/python-websocket.md
详细介绍
WebSocket 实现
构建具备完善连接管理的可扩展实时通信系统。
服务端实现(Socket.IO)
const { Server } = require('socket.io');
const { createAdapter } = require('@socket.io/redis-adapter');
const { createClient } = require('redis');
const io = new Server(server, {
cors: { origin: process.env.CLIENT_URL, credentials: true }
});
// Redis adapter for horizontal scaling
const pubClient = createClient({ url: process.env.REDIS_URL });
const subClient = pubClient.duplicate();
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
io.adapter(createAdapter(pubClient, subClient));
});
// Connection management
const users = new Map();
io.use((socket, next) => {
const token = socket.handshake.auth.token;
try {
socket.user = verifyToken(token);
next();
} catch (err) {
next(new Error('Authentication failed'));
}
});
io.on('connection', (socket) => {
users.set(socket.user.id, socket.id);
console.log(`User ${socket.user.id} connected`);
socket.on('join-room', (roomId) => {
socket.join(roomId);
socket.to(roomId).emit('user-joined', socket.user);
});
socket.on('message', ({ roomId, content }) => {
io.to(roomId).emit('message', {
userId: socket.user.id,
content,
timestamp: Date.now()
});
});
socket.on('disconnect', () => {
users.delete(socket.user.id);
});
});
// Utility methods for message distribution
function broadcastUserUpdate(userId, data) {
io.to(`user:${userId}`).emit('user-update', data);
}
function notifyRoom(roomId, event, data) {
io.to(`room:${roomId}`).emit(event, data);
}
function sendDirectMessage(userId, message) {
const socketId = users.get(userId);
if (socketId) {
io.to(socketId).emit('direct-message', message);
}
}
客户端实现
import { io } from 'socket.io-client';
class WebSocketClient {
constructor(url, token) {
this.socket = io(url, {
auth: { token },
reconnection: true,
reconnectionDelay: 1000,
reconnectionAttempts: 5
});
this.messageQueue = [];
this.setupListeners();
}
setupListeners() {
this.socket.on('connect', () => {
console.log('Connected');
this.flushQueue();
});
this.socket.on('disconnect', (reason) => {
console.log('Disconnected:', reason);
});
this.socket.on('message', (msg) => {
this.onMessage?.(msg);
});
}
joinRoom(roomId) {
this.socket.emit('join-room', roomId);
}
send(roomId, content) {
if (this.socket.connected) {
this.socket.emit('message', { roomId, content });
} else {
this.messageQueue.push({ roomId, content });
}
}
flushQueue() {
while (this.messageQueue.length > 0) {
const msg = this.messageQueue.shift();
this.socket.emit('message', msg);
}
}
}
React Hook
function useWebSocket(url) {
const [socket, setSocket] = useState(null);
const [connected, setConnected] = useState(false);
const [messages, setMessages] = useState([]);
useEffect(() => {
// getToken() is a user-supplied helper that returns the current auth token
// Example implementations:
// - From localStorage: () => localStorage.getItem('authToken')
// - From context: () => authContext.token
// - From cookie: () => document.cookie.split('token=')[1]
const ws = io(url, { auth: { token: getToken() } });
ws.on('connect', () => setConnected(true));
ws.on('disconnect', () => setConnected(false));
ws.on('message', (msg) => {
setMessages(prev => [...prev, msg]);
});
setSocket(ws);
return () => ws.disconnect();
}, [url]);
const send = useCallback((roomId, content) => {
socket?.emit('message', { roomId, content });
}, [socket]);
return { connected, messages, send };
}
消息协议
interface Message {
type: 'message' | 'typing' | 'presence';
roomId: string;
userId: string;
content?: string;
timestamp: number;
}
// Acknowledge delivery
socket.emit('message', data, (ack) => {
if (ack.success) console.log('Delivered');
});
其他实现
请参阅 references/python-websocket.md,了解:
- Python aiohttp WebSocket 服务端
- FastAPI WebSocket 端点
- 异步连接处理
扩展性考量
| 连接数 | 架构 |
|---|---|
| <10K | 单个服务端 |
| 10K-100K | Redis pub/sub |
| >100K | 分片 Redis + 负载均衡器 |
监控端点
// Express endpoints for operational visibility
app.get('/api/ws/stats', (req, res) => {
res.json({
activeConnections: io.sockets.sockets.size,
rooms: [...io.sockets.adapter.rooms.keys()],
users: users.size
});
});
app.get('/api/ws/health', (req, res) => {
res.json({
status: 'healthy',
uptime: process.uptime(),
memoryUsage: process.memoryUsage()
});
});
最佳实践
- 允许执行操作前先进行身份验证
- 使用指数退避机制实现重新连接
- 使用房间和频道进行定向广播
- 添加心跳/ping 以检查连接状态
- 将重要消息持久化到数据库
- 监控活动连接数
- 显示用户在线/可用状态
- 对传入消息实施速率限制
- 使用确认机制确认消息已送达
- 在分布式部署中使用 Redis
- 实施全面的错误处理
切勿执行
- 发送未加密的敏感数据
- 在内存中存储无限量消息
- 加入房间时跳过授权检查
- 忽略连接错误处理
- 允许不受限制地订阅房间
- 忽略清理已断开连接用户的数据
- 频繁发送过大的消息负载
- 在消息正文中包含身份验证凭据
- 未经安全验证就进行部署
- 允许连接数不受控制地累积
- 构建时不考虑可扩展性
评论
支持 Markdown