Inicio > Cursos > Node.js y Express > WebSockets con Socket.io
Node.js y ExpressBases de Datos y APIsLección 14 de 20

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'));
ConsejoDiferencia clave: socket.emit() envía solo al cliente actual. socket.to(room).emit() envía a todos en la room excepto el emisor. io.to(room).emit() envía a TODOS en la room incluyendo el emisor.
← API REST CompletaSubida de Archivos →

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