mcpField
W
websocket-implementation

websocket-implementation

github.com/secondsky开发242434 次安装5 周前更新
代码仓库

关于 websocket-implementation

面向构建实时应用的开发者,提供 WebSocket 服务端与客户端实现指导,涵盖 Socket.IO、React 集成、扩展和运行监控。

主要功能

  1. 01Socket.IO 服务端与客户端模式
  2. 02React WebSocket Hook 示例
  3. 03消息协议设计
  4. 04基于 Redis 的扩展建议
  5. 05连接监控端点

适用场景

  1. 01构建实时消息功能
  2. 02管理经过身份验证的 WebSocket 连接
  3. 03使用 Redis 扩展部署
  4. 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-100KRedis 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