Preguntas frecuentes sobre el protocolo WebSocket

WebSocket es un protocolo relativamente nuevo que surgió junto con la especificación de HTML5. A pesar de su juventud, la mayoría de los navegadores modernos ya lo soportan. Su uso es amplio y se ha integrado en diversos escenarios del desarrollo frontend y backend.

La insatisfacción con el modelo de comunicación unidireccional HTTP "pregunta-respuesta" dio lugar al desarrollo de WebSocket, que permite comunicación bidireccional. WebSocket es un protocolo no convencional.

  1. ¿Solo pueden iniciar conexiones WebSocket los navegadores? ===============================================

No. El público objetivo actual del protocolo no se limita únicamente a desarrolladores web.

WebSocket es simplemente un protocolo, similar a HTTP. Se puede invocar desde cualquier lugar usando componentes como OkHttp, e incluso se puede utilizar para construir marcos RPC.

  1. ¿Cuál es la relación entre WebSocket y HTTP? ====================================

Tanto WebSocket como HTTP operan en la capa de aplicación del modelo OSI.

WebSocket utiliza HTTP para realizar el handshake. Una vez completado, se convierte en un canal TCP y deja de interactuar con HTTP. Con herramientas como netstat o ss, se puede observar la conexión correspondiente, que no difiere visualmente de un socket abstracto.

  1. ¿Qué diferencia hay entre WebSocket y polling largo? ============================================

El polling largo consiste en que el cliente envía una solicitud y el servidor mantiene la conexión hasta que hay datos disponibles, siguiendo aún el patrón pregunta-respuesta. Ejemplos incluyen Comet.

WebSocket, tras el handshake exitoso, crea un canal TCP full-duplex donde el servidor puede enviar datos activamente al cliente sin necesidad de esperar una solicitud. Las aplicaciones en ambos extremos son equivalentes.

Las conexiones WebSocket difieren de las conexiones largas HTTP. Dado que las conexiones HTTP largas siguen siendo basadas en HTTP, siguen siendo pregunta-respuesta, solo manteniendo una conexión prolongada. El polling largo y las conexiones HTTP largas son E/S bloqueantes, mientras que WebSocket puede ser no bloqueante (mediante multiplexión).

  1. ¿Cómo se establece una conexión? ========================

Las conexiones WebSocket se inicializan mediante HTTP para garantizar compatibilidad. Esto permite crear solicitudes fácilmente desde navegadores, aunque esto puede ser engañoso.

La siguiente imagen muestra una solicitud ws típica desde un navegador, que se parece mucho a una solicitud HTTP. Sin embargo, solo se parece durante la fase de solicitud:

La dirección de la solicitud suele ser ws://*** o wss: si usa SSL/TLS, indicando una solicitud WebSocket. 1. Primero, se utiliza el campo Upgrade en los encabezados HTTP para solicitar cambio de protocolo. Si el servidor lo acepta, se cambia a WebSocket. Básicamente: la conexión ya existe, se hace un handshake para cambiar a protocolo ws, cambiando solo el estado de la conexión.

  1. El campo Connection actúa como complemento del campo Upgrade. Servidores proxy como nginx deben procesar Connection antes de realizar el cambio de protocolo.

Sec-WebSocket-Key es una cadena aleatoria. El servidor genera un resumen SHA-1 con estos datos para evitar que solicitudes HTTP normales sean interpretadas como WebSocket.

Otros encabezados como Sec-WebSocket*, indican subprotocolos compatibles por el cliente. Por ejemplo, MQTT puede usarse como subprotocolo WebSocket.

Con JavaScript, conectar a un servidor WebSocket es sencillo:

<script>
  var ws = new WebSocket('ws://localhost:80');
  ws.onopen = function () {
    console.log('ws onopen');
    ws.send('from client: hello');
  };
  ws.onmessage = function (e) {
    console.log('ws onmessage');
    console.log('from server: ' + e.data);
  };
  ...
</script>

  1. ¿Cómo se manejan los datos? ===================

WebSocket opera mediante notificaciones de eventos. Tiene cuatro eventos y dos acciones (envío y cierre).

Eventos de WebSocket

Evento Hook Notas
open onopen Se dispara cuando se establece la conexión
message onmessage Se dispara al recibir datos del servidor
error onerror Se dispara cuando ocurre un error de comunicación
close onclose Se dispara cuando se cierra la conexión

Los datos se transmiten directamente mediante el método Socket.send().

En Chrome, se puede ver la conexión WebSocket en Inspect -> Network -> WS. La imagen muestra un frame binario con Opcode 2.

WebSocket tiene un formato de frame similar al protocolo TCP, pero no se explicará aquí en detalle. Referencia: tools.ietf.org/html/rfc645…

Latencia

Las operaciones ping/pong corresponden a opcodes 0x9 y 0xA. El receptor debe actualizar internamente el tiempo de latencia. En entornos móviles, se requiere un control inteligente de latencia.

  1. ¿Cómo configurar balanceo de carga con Nginx? =======================================

El sitio oficial de nginx proporciona ejemplos. Principalmente se enfoca en los encabezados Upgrade y Connection.

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

location /chat/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
}

Es importante destacar que Nginx no necesita configuraciones como ip_hash para balanceo de carga, ya que lo soporta nativamente. ip_hash solo usa los primeros tres dígitos de la IP, lo cual puede causar desequilibrio en el servidor.

  1. ¿Cómo implementar un servidor Java? =============================

Se puede usar el paquete javax.websocket para implementar un servidor WebSocket. Actualmente se puede programar mediante anotaciones, como ServerEndpoint.

Se recomienda usar netty-socketio basado en Netty. Al usar Netty, se puede acceder a múltiples niveles para obtener estadísticas y ejecutar comandos de control. SocketIO es una solución completa con clientes en múltiples lenguajes y resuelve problemas de compatibilidad comunes.

  1. ¿Qué se puede hacer con WebSocket? ==========================

Notificaciones

Mantener una conexión persistente permite enviar mensajes nuevos al cliente en tiempo real. Notificaciones como "me gusta" o comentarios en Zhihu pueden usar esta tecnología. Algunos clientes H5 también usan WebSocket para notificaciones, ofreciendo mejor experiencia de usuario.

Recopilación de datos

Datos secundarios como registros de comportamiento, traces o stacks de excepciones pueden enviarse por canales WebSocket dedicados. Esto centraliza información y permite configuraciones dinámicas según el comportamiento del usuario. Dado que la mayoría de los navegadores lo soportan, simplifica modelos de programación APM en clientes.

Cifrado y autenticación

Aunque herramientas como Fiddler o Charles pueden capturar paquetes WebSocket, el uso de SSL aumenta significativamente el costo de descifrado, haciendo la comunicación más segura.

Hooks de control inverso

Dado que es una conexión full-duplex, el servidor puede enviar comandos o incluso código ejecutable al cliente. Por ejemplo, tomar capturas de pantalla, grabar audio o implantar backdoors. Solo necesitas autorización del usuario para ejecutar estas funciones.

El chiste de Alipay accediendo a tu cámara para tomarte fotos es creíble.

Referencia: https://juejin.im/post/5c9ad3ecf265da61173a43ab

Etiquetas: WebSocket HTTP protocol java Nginx

Publicado el 9-24 07:14