Protocolo WebSocket y proceso de Handshake inicial

El protocolo WebSocket (definido en el estándar RFC 6455) comienza como una conexión HTTP y luego se transforma en un canal persistente y bidireccional.

Este proceso de transformación se llama handshake (apretón de manos):

  • El cliente pide al servidor actualizar la conexión HTTP a WebSocket.
  • El servidor acepta, confirma y cambia el protocolo.
  • A partir de ahí, el canal deja de ser HTTP y pasa a ser WebSocket.

Paso 1 — Petición inicial del cliente

El cliente (por ejemplo, un navegador usando la API WebSocket) abre una conexión:

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

Esto genera una petición HTTP estándar, pero con cabeceras especiales:

GET /chat HTTP/1.1
Host: localhost:8080
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: http://localhost:3000

Campos importantes:

  • Upgrade: websocket — solicita cambiar de protocolo.
  • Connection: Upgrade — confirma la intención de actualización.
  • Sec-WebSocket-Key — clave aleatoria en Base64, usada por el servidor para autenticar la petición.
  • Sec-WebSocket-Version: 13 — versión estándar y obligatoria.
  • Origin — indica el origen de la conexión (útil para seguridad).

Paso 2 — Respuesta del servidor

Si el servidor acepta, responde:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

Campos importantes:

  • 101 Switching Protocols — código que indica el cambio de protocolo.
  • Upgrade/Connection: Upgrade — confirman la actualización.
  • Sec-WebSocket-Accept — valor calculado a partir de la clave del cliente.

Paso 3 — Validación de clave (Sec-WebSocket-Accept)

El servidor toma la clave del cliente (Sec-WebSocket-Key) y calcula:

Sec-WebSocket-Accept = Base64( SHA-1( Sec-WebSocket-Key + GUID ) )

Donde la GUID es la cadena fija 258EAFA5-E914-47DA-95CA-C5AB0DC85B11. Conceptos relacionados: SHA‑1, Base64.

Ejemplo:

Sec-WebSocket-Key = dGhlIHNhbXBsZSBub25jZQ==
Concatenar GUID → dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
SHA-1 (hash binario)
Base64 → s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

El servidor devuelve este valor en Sec-WebSocket-Accept. Esto garantiza que el servidor entiende el protocolo WebSocket.

Paso 4 — Conexión establecida

  • Una vez recibido el 101 Switching Protocols y validada la cabecera, el protocolo cambia oficialmente a WebSocket.
  • Ya no se intercambian peticiones/respuestas HTTP: ahora se envían frames WebSocket (texto, binario, control).
  • La conexión se mantiene hasta que alguna de las partes la cierre.

Ejemplo real con Node.js (librería ws)

Servidor (server.js)

const WebSocket = require("ws");

const wss = new WebSocket.Server({ port: 8080 }, () => {
  console.log("Servidor WebSocket en ws://localhost:8080");
});

wss.on("connection", (ws) => {
  console.log("Cliente conectado (handshake exitoso)");
  ws.send("Conexión establecida!");
});

Cliente (navegador)

<script>
  const ws = new WebSocket("ws://localhost:8080");
  ws.onopen = () => console.log("Handshake completado");
  ws.onmessage = (e) => console.log("Servidor:", e.data);
</script>

Para este ejemplo se usa Node.js y la librería ws.

Handshake visto en el navegador (DevTools)

  1. Abrir el cliente (ws://localhost:8080).
  2. F12 → pestaña Network → filtro WS.
  3. Seleccionar la conexión → pestaña Headers.

Verás algo como:

Request
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JtP3zBxGJdd+2ZsHGyVQ==
Sec-WebSocket-Version: 13

Response
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: Z6Fx0DdFfCzD4V4Zf2oV1OxT9fQ=

ws:// vs wss://

  • ws:// — WebSocket sin cifrar (recomendado solo en desarrollo).
  • wss:// — WebSocket cifrado con TLS (equivalente a HTTPS).

Ejemplo de cliente seguro:

const ws = new WebSocket("wss://mi-servidor.com/socket");

En producción, usa siempre wss:// para proteger los datos y evitar ataques de intermediarios (man‑in‑the‑middle).

En resumen

  • El protocolo WebSocket comienza como una petición HTTP con Upgrade: websocket.
  • El servidor responde con 101 Switching Protocols y una clave validada (Sec-WebSocket-Accept).
  • Tras el handshake, la conexión pasa a ser un canal persistente y bidireccional, capaz de intercambiar frames en tiempo real.