6. WebSocket: comunicación bidireccional en tiempo real

WebSocket ofrece un canal full-duplex persistente sobre TCP que permite intercambiar mensajes entre navegador y servidor sin rehacer la negociación completa en cada evento. Se apoya en un handshake HTTP inicial para luego “actualizar” la conexión a un protocolo más liviano, ideal para chats, trading, telemetría e IoT.

6.1 Concepto: canal persistente entre cliente y servidor

WebSocket mantiene un socket abierto en ambas direcciones. Una vez establecido, cualquiera de las partes puede enviar mensajes cuando lo necesite, lo que reduce la latencia y el uso de ancho de banda frente a técnicas como long polling o HTTP corto.

Elemento Descripción
Canal Se abre un único socket que permanece activo hasta que una parte lo cierre.
Mensajes Se transmiten como frames de texto o binarios, con soporte para fragmentación.
Control Frames especiales como ping/pong mantienen vivo el canal.

6.2 Diferencias con HTTP tradicional (petición-respuesta)

HTTP está pensado para transacciones independientes. El cliente inicia una solicitud y espera la respuesta. WebSocket reemplaza este patrón por una conversación continua. Las diferencias clave son:

  • Direccionalidad: en HTTP solo el servidor responde; con WebSocket ambos pueden iniciar mensajes.
  • Persistencia: el socket se mantiene abierto durante minutos u horas sin renegociar TLS o autenticación.
  • Eficiencia: se evitan cabeceras repetidas y se ahorra batería en móviles porque no se crean conexiones nuevas.
  • Estado compartido: es más sencillo propagar cambios simultáneos a muchos clientes (broadcast).

Esto no significa que WebSocket reemplace a HTTP, sino que lo complementa para los casos donde la inmediatez es imprescindible.

6.3 Flujo de conexión: handshake HTTP → canal WebSocket (WS/WSS)

Para abrir un WebSocket se realiza primero una petición HTTP con cabeceras especiales que solicitan al servidor cambiar el protocolo:

  1. El cliente envía un GET con cabeceras Upgrade: websocket, Connection: Upgrade y un Sec-WebSocket-Key.
  2. El servidor verifica la solicitud y responde con 101 Switching Protocols más Sec-WebSocket-Accept.
  3. A partir de ese momento se deja de hablar HTTP y se envían frames WebSocket con los datos de la aplicación.

Cuando la conexión se cifra, se utiliza el esquema wss:// (WebSocket Secure) que encapsula el tráfico dentro del mismo túnel TLS que HTTPS. De esta forma se protege la confidencialidad y se evita que proxies modifiquen el contenido.

6.4 Ejemplos de uso: chats, videojuegos, dashboards, trading e IoT

WebSocket es habitual en escenarios de baja latencia donde hay múltiples eventos por segundo. Algunos casos representativos:

  • Chats y mensajería: cada mensaje se distribuye instantáneamente a todos los participantes conectados.
  • Videojuegos multijugador: sincroniza posiciones y acciones sin esperar nuevas solicitudes HTTP.
  • Dashboards industriales o financieros: las métricas se actualizan en pantallas sin necesidad de refrescar.
  • Trading y bolsas: el servidor emite cotizaciones cada pocos milisegundos.
  • IoT: sensores de alto volumen publican eventos a un gateway que replica la información a sistemas analíticos.

Otra ventaja es la compatibilidad nativa con prácticamente todos los navegadores modernos, lo que simplifica su adopción.

6.5 Protocolo de subnivel TCP (puertos 80/443)

WebSocket se transporta encima de TCP. Habitualmente reusa los puertos 80 (ws://) y 443 (wss://) porque el handshake es un HTTP común. Esto facilita atravesar firewalls y balanceadores existentes.

Consideraciones al desplegarlo:

  • Keep-alive: configurar intervalos de ping/pong para detectar clientes caídos y liberar recursos.
  • Backpressure: implementar colas para evitar que un cliente lento bloquee al resto; TCP por sí solo no resuelve la lógica de aplicación.
  • Escalabilidad: los servidores deben manejar miles de sockets concurrentes; frameworks como Node.js, Go o Elixir manejan bien este patrón.

También es común usar WSS detrás de proxies como Nginx o Envoy, que se encargan de terminar TLS y reenviar el tráfico al backend que mantiene los sockets.

6.6 Ejemplo práctico: new WebSocket("wss://...")

El API del navegador resulta muy simple. Basta con instanciar un objeto WebSocket y registrar eventos:

const socket = new WebSocket("wss://echo.websocket.events");

socket.addEventListener("open", () => {
  console.log("Canal abierto");
  socket.send(JSON.stringify({ tipo: "ping", ts: Date.now() }));
});

socket.addEventListener("message", (event) => {
  const data = JSON.parse(event.data);
  console.log("Mensaje recibido:", data);
});

socket.addEventListener("close", () => {
  console.log("Canal cerrado");
});

Con unas pocas líneas ya tenemos comunicación bidireccional. Para entornos productivos se recomienda añadir reconexiones automáticas y autenticación basada en tokens o cookies firmadas para evitar accesos no autorizados.