WebSocket en TypeScript: técnicas avanzadas para aplicaciones en tiempo real

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

WebSocket en TypeScript: Técnicas Avanzadas para Aplicaciones en Tiempo Real



WebSocket proporciona una conexión bidireccional persistente entre cliente y servidor, lo que lo hace ideal para aplicaciones en tiempo real: chats, notificaciones, edición colaborativa y juegos en línea. En este artículo, exploraremos técnicas avanzadas para trabajar con WebSocket en TypeScript, yendo más allá de un simple servidor echo.



1. Arquitectura con Gestión de Salas (Rooms)



En aplicaciones reales, rara vez se utiliza la transmisión global a todos los clientes. Mucho más a menudo se requiere la separación lógica de los clientes en salas (por ejemplo, salas de chat o sesiones de juego). Veamos una implementación en TypeScript usando la librería ws.



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); });});


Este código demuestra una gestión segura de salas: creación bajo demanda, limpieza automática de salas vacías y exclusión del remitente de la transmisión.



2. Autenticación y Gestión de Estado



Las conexiones WebSocket deben ser autenticadas. Un enfoque avanzado es la verificación de tokens al establecer la conexión y el mantenimiento de la sesión.



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 { // Aquí debería ir la validación real del JWT u otro token return token.length > 10;}

wss.on('co

Blogs

Book Recommendations