WebSocket on TypeScript: Real-Time 应用的高级技巧
WebSocket 在客户端和服务器之间提供持久的双向连接,使其成为实时应用的理想选择:聊天、通知、协作编辑和在线游戏。在本文中,我们将探讨在 TypeScript 中使用 WebSocket 的高级技巧,超越简单的回声服务器。
1. 带有房间管理的架构(Rooms)
在实际应用中,很少使用全局广播给所有客户端。更常见的是需要将客户端逻辑上分成房间(例如聊天室或游戏会话)。让我们看看使用 ws 库在 TypeScript 中的实现。
import { WebSocketServer, WebSocket } from 'ws';
interface Room { id: string; clients: Set<WebSocket>;}
class RoomManager { private rooms: Map<string, Room> = new Map();
createRoom(roomId: string): void { if (!this.rooms.has(roomId)) { this.rooms.set(roomId, { id: roomId, clients: new Set() }); } }
joinRoom(roomId: string, client: WebSocket): void { this.createRoom(roomId); this.rooms.get(roomId)!.clients.add(client); client.send(JSON.stringify({ type: 'room_joined', roomId })); }
leaveRoom(roomId: string, client: WebSocket): void { const room = this.rooms.get(roomId); if (room) { room.clients.delete(client); if (room.clients.size === 0) { this.rooms.delete(roomId); } } }
broadcastToRoom(roomId: string, message: object, sender?: WebSocket): void { const room = this.rooms.get(roomId); if (room) { const data = JSON.stringify(message); room.clients.forEach(client => { if (client.readyState === WebSocket.OPEN && client !== sender) { client.send(data); } }); } }}
const wss = new WebSocketServer({ port: 8080 });const roomManager = new RoomManager();
wss.on('connection', (ws: WebSocket) => { ws.on('message', (raw: Buffer) => { try { const msg = JSON.parse(raw.toString()); switch (msg.type) { case 'join': roomManager.joinRoom(msg.roomId, ws); break; case 'leave': roomManager.leaveRoom(msg.roomId, ws); break; case 'message': roomManager.broadcastToRoom(msg.roomId, { type: 'chat', user: msg.user, text: msg.text }, ws); break; } } catch (e) { ws.send(JSON.stringify({ type: 'error', message: 'Invalid JSON' })); } });
ws.on('close', () => { // Cleanup: remove client from all rooms roomManager.leaveRoom('*', ws); });});这段代码演示了安全的房间管理:按需创建、自动清理空房间,以及将发送者排除在广播之外。
2. 身份认证和状态管理
WebSocket 连接必须经过身份验证。一种高级方法是在建立连接时进行令牌验证并维护会话。
import { IncomingMessage } from 'http';import { WebSocketServer, WebSocket } from 'ws';
interface AuthenticatedSocket extends WebSocket { userId?: string; username?: string;}
const wss = new WebSocketServer({ port: 8080, verifyClient: (info: { req: IncomingMessage }, callback: (res: boolean) => void) => { const token = extractToken(info.req.url || ''); if (token && validateToken(token)) { callback(true); } else { callback(false); } }});
function extractToken(url: string): string | null { const params = new URLSearchParams(url.split('?')[1] || ''); return params.get('token');}
function validateToken(token: string): boolean { // Here should be actual JWT or other token validation return token.length > 10;}
wss.on('co