关于 socket-io
Socket.IO 是用于构建服务器与客户端实时通信的库,示例涵盖类型化事件、身份验证、重连和 React 房间处理。README 还展示了使用 Redis Adapter 扩展到多台服务器的配置。
主要功能
- 01服务器与客户端连接示例
- 02类型化事件定义
- 03身份验证和重连选项
- 04基于房间的消息处理
- 05用于多服务器扩展的 Redis Adapter
- 06React hook 示例
适用场景
- 01构建带房间的实时聊天
- 02处理经过身份验证的客户端连接
- 03将 Socket.IO 扩展至多台服务器
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill socket-io安装后在 Claude Code 中输入/socket-io确认已加载。
详细介绍
Socket.IO
服务端设置
import { Server } from 'socket.io';
import { createServer } from 'http';
const httpServer = createServer(app);
interface ServerToClientEvents {
message: (data: { user: string; text: string; timestamp: number }) => void;
userJoined: (user: string) => void;
}
interface ClientToServerEvents {
sendMessage: (text: string, callback: (status: 'ok' | 'error') => void) => void;
joinRoom: (room: string) => void;
}
const io = new Server<ClientToServerEvents, ServerToClientEvents>(httpServer, {
cors: { origin: process.env.CLIENT_URL },
});
// Authentication middleware
io.use((socket, next) => {
const token = socket.handshake.auth.token;
try {
socket.data.user = verifyToken(token);
next();
} catch {
next(new Error('Authentication failed'));
}
});
io.on('connection', (socket) => {
console.log(`${socket.data.user.name} connected`);
socket.on('joinRoom', (room) => {
socket.join(room);
socket.to(room).emit('userJoined', socket.data.user.name);
});
socket.on('sendMessage', (text, callback) => {
const message = { user: socket.data.user.name, text, timestamp: Date.now() };
io.to('general').emit('message', message);
callback('ok');
});
socket.on('disconnect', () => {
console.log(`${socket.data.user.name} disconnected`);
});
});
客户端设置
import { io, Socket } from 'socket.io-client';
const socket: Socket<ServerToClientEvents, ClientToServerEvents> = io(API_URL, {
auth: { token: getAuthToken() },
reconnection: true,
reconnectionDelay: 1000,
});
socket.on('connect', () => console.log('Connected'));
socket.on('message', (data) => addMessage(data));
socket.on('connect_error', (err) => console.error(err.message));
// With acknowledgment
socket.emit('sendMessage', 'Hello!', (status) => {
if (status === 'error') showError('Failed to send');
});
使用 Redis 适配器进行扩展
import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';
const pubClient = createClient({ url: process.env.REDIS_URL });
const subClient = pubClient.duplicate();
await Promise.all([pubClient.connect(), subClient.connect()]);
io.adapter(createAdapter(pubClient, subClient));
React Hook
function useSocket(room: string) {
const [messages, setMessages] = useState<Message[]>([]);
useEffect(() => {
socket.emit('joinRoom', room);
socket.on('message', (msg) => setMessages((prev) => [...prev, msg]));
return () => { socket.off('message'); };
}, [room]);
const send = (text: string) => socket.emit('sendMessage', text, () => {});
return { messages, send };
}
反模式
| 反模式 | 修复方法 |
|---|---|
| 不进行身份验证 | 使用带 JWT 的 io.use() 中间件 |
| 向所有客户端广播,而不是向房间广播 | 使用 socket.to(room).emit() |
| 不处理重新连接 | 启用重新连接,并显示 UI 指示器 |
| 单服务器且未使用适配器 | 使用 Redis 适配器进行水平扩展 |
| 关键事件没有确认机制 | 使用回调参数确认送达 |
生产环境检查清单
- 连接时使用身份验证中间件
- 多服务器部署使用 Redis 适配器
- 使用指数退避机制重新连接
- 基于房间限定消息范围
- 显示连接状态 UI 指示器
- 对消息事件进行速率限制
评论
支持 Markdown