WebSockets con Socket.io
HTTP es unidireccional: el cliente pregunta, el servidor responde, la conexión se cierra. WebSockets crean un canal permanente bidireccional: el servidor puede enviar datos al cliente en cualquier momento sin que el cliente los pida. Esto es lo que permite los chats en tiempo real, las notificaciones instantáneas y los juegos multijugador.
Socket.io es la librería más popular para WebSockets en Node.js. Agrega reconexión automática cuando se cae la conexión, rooms para agrupar usuarios (ej. una sala de chat), namespaces para separar lógicas en el mismo servidor, y fallback a long-polling en redes que bloquean WebSockets. Con 5 líneas de código tienes un chat funcional.
// npm install socket.io
const { createServer } = require('http');
const { Server } = require('socket.io');
const express = require('express');
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, {
cors: { origin: '*', methods: ['GET', 'POST'] }
});
// Middleware de Socket.io para autenticación
io.use((socket, next) => {
const token = socket.handshake.auth.token;
try {
const user = jwt.verify(token, process.env.JWT_SECRET);
socket.user = user; // disponible en todos los eventos
next();
} catch {
next(new Error('Token inválido'));
}
});
// Manejo de conexiones
io.on('connection', (socket) => {
console.log(`Usuario ${socket.user.nombre} conectado [${socket.id}]`);
// Unirse a una sala (room)
socket.on('unirseChat', (chatId) => {
socket.join(`chat:${chatId}`); // puede estar en múltiples rooms
socket.to(`chat:${chatId}`).emit('usuarioUnido', {
usuario: socket.user.nombre
});
});
// Enviar mensaje a todos en una sala
socket.on('mensaje', async ({ chatId, texto }) => {
const mensaje = await db.mensaje.create({
data: { texto, usuarioId: socket.user.userId, chatId }
});
// Emitir a TODOS en la sala (incluido el emisor)
io.to(`chat:${chatId}`).emit('nuevoMensaje', mensaje);
});
// Indicador de "escribiendo..."
socket.on('escribiendo', ({ chatId }) => {
// broadcast = a todos MENOS al emisor
socket.to(`chat:${chatId}`).emit('usuarioEscribiendo', {
usuario: socket.user.nombre
});
});
// Salir de sala
socket.on('salirChat', (chatId) => {
socket.leave(`chat:${chatId}`);
});
socket.on('disconnect', () => {
console.log(`${socket.user.nombre} desconectado`);
});
});
httpServer.listen(3000, () => console.log('Servidor con WebSockets listo'));
Practica esta lección
Resuelve los ejercicios del curso de Node.js y Express en la app, gratis y con corrección automática.
Empezar a practicar