Ciclo de vida de una conexión WebSocket

Una conexión WebSocket no es simplemente abrir y cerrar. El protocolo define un ciclo de vida con distintos estados, eventos asociados y mensajes de control que garantizan un intercambio ordenado.

Este ciclo puede dividirse en cuatro etapas principales:

  • Establecimiento (handshake)
  • Conexión abierta y comunicación activa
  • Mantenimiento (pings/pongs, errores, reconexión)
  • Cierre controlado o inesperado

Estados de la conexión WebSocket

En JavaScript, un objeto WebSocket puede estar en uno de los siguientes estados (ws.readyState):

  • 0 — CONNECTING: el cliente ha creado el socket pero aún está realizando el handshake con el servidor.
  • 1 — OPEN: la conexión está activa y se pueden enviar/recibir mensajes.
  • 2 — CLOSING: alguna de las partes inició el cierre; se están enviando frames de close.
  • 3 — CLOSED: la conexión ha terminado definitivamente.

Estos valores son constantes accesibles como WebSocket.CONNECTING, WebSocket.OPEN, etc.

Etapas detalladas del ciclo de vida

1. Establecimiento (Handshake)

  • El cliente envía una petición HTTP con Upgrade: websocket.
  • El servidor responde con 101 Switching Protocols.
  • Si todo es correcto, se pasa a estado OPEN.

2. Conexión abierta

  • Se habilita la comunicación bidireccional (full‑dúplex).
  • Tanto cliente como servidor pueden enviar mensajes (texto, binario).
  • Eventos típicos: onopen (conexión lista) y onmessage (recepción de mensajes).

3. Mantenimiento

  • Para verificar que la conexión sigue viva, el servidor puede enviar un Ping y el cliente responde automáticamente con Pong.
  • Esto evita que la conexión quede colgada en caso de pérdida de red.
  • Si hay errores (por ejemplo, desconexión de red), se activa el evento onerror.

4. Cierre de conexión

  • Puede ser iniciado por el cliente o el servidor.
  • Se envía un frame de cierre (opcode 0x8), que puede incluir un código de estado y un mensaje opcional.
  • La otra parte responde con su propio frame de cierre.
  • El estado pasa a CLOSING y finalmente a CLOSED.
  • Evento asociado: onclose.

Diagrama de ciclo de vida

   +---------------------+
   |   CONNECTING (0)    |
   +----------+----------+
              |
              v
   +---------------------+
   |      OPEN (1)       |
   | (mensajes libres)   |
   +----------+----------+
              |
              v
   +---------------------+
   |     CLOSING (2)     |
   | (frames de cierre)  |
   +----------+----------+
              |
              v
   +---------------------+
   |     CLOSED (3)      |
   +---------------------+
          

Ejemplo en JavaScript (cliente)

const ws = new WebSocket("ws://localhost:8080");

// Estado inicial
console.log("Estado inicial:", ws.readyState); // 0 (CONNECTING)

ws.onopen = () => {
  console.log("Conexión abierta");
  console.log("Estado:", ws.readyState); // 1 (OPEN)
  ws.send("¡Hola servidor!");
};

ws.onmessage = (event) => {
  console.log("Mensaje recibido:", event.data);
};

ws.onerror = (error) => {
  console.error("Error en WS:", error);
};

ws.onclose = (event) => {
  console.log("Conexión cerrada");
  console.log("Código:", event.code, "Razón:", event.reason);
};

Si cerrás el servidor o el cliente, se disparará el evento onclose.

Ejemplo de cierre desde el servidor (Node.js con ws)

const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 8080 });

wss.on("connection", (ws) => {
  console.log("Cliente conectado");
  ws.send("¡Bienvenido!");

  // Cerrar después de 5 segundos
  setTimeout(() => {
    ws.close(1000, "Fin de la sesión");
    // 1000 = código de cierre normal
  }, 5000);
});
Secuencia de cierre WebSocket: onclose con code 1000 y reason 'Fin de la sesión'

En el cliente, onclose recibirá code: 1000 y reason: "Fin de la sesión".

Referencias y herramientas

Códigos de cierre comunes

  • 1000 — Cierre normal.
  • 1001 — El cliente se va (p. ej., el navegador cierra la pestaña).
  • 1006 — Cierre anómalo (sin frame de cierre).
  • 1009 — Mensaje demasiado grande.
  • 1011 — Error inesperado en el servidor.

En resumen

El ciclo de vida de una conexión WebSocket pasa por CONNECTING → OPEN → CLOSING → CLOSED, con eventos bien definidos (onopen, onmessage, onerror, onclose). Gracias a este modelo, el protocolo maneja mensajes en tiempo real de forma ordenada y confiable.