What is a WebSocket event?

Ws: Protocolo WebSocket y la Librería de Node.js

hace 10 años

★★★★★Valoración: 4.62 (2830 votos)

En el mundo del desarrollo web moderno, la comunicación en tiempo real se ha convertido en una necesidad fundamental. Ya sea para aplicaciones de chat, actualizaciones en vivo, juegos multijugador o notificaciones instantáneas, la capacidad de intercambiar datos de manera bidireccional y con baja latencia es crucial. Aquí es donde entra en juego WebSocket, una tecnología revolucionaria que ha transformado la forma en que las aplicaciones web interactúan con los servidores. Y cuando hablamos de implementar WebSockets en el ecosistema de Node.js, la librería ws emerge como una solución robusta, eficiente y ampliamente adoptada.

What is ws used for?
It enables real-time data exchange between a client (e.g., web browser) and a server. Connections are established with an HTTP/HTTPS handshake using ws:// or wss:// schemes, where the client sends an Upgrade: websocket header, and the server responds with 101 Switching Protocols .

¿Qué es WebSocket? El Protocolo y la API Explicados

WebSocket es un protocolo de comunicación que permite una conexión persistente y bidireccional entre un cliente (como un navegador web) y un servidor. A diferencia del modelo tradicional HTTP, que se basa en solicitudes y respuestas, WebSocket establece un canal de comunicación full-duplex, lo que significa que tanto el cliente como el servidor pueden enviar datos simultáneamente una vez que la conexión se ha establecido. Esta conexión permanece abierta durante el tiempo que sea necesario, eliminando la necesidad de realizar múltiples solicitudes HTTP para intercambiar datos en tiempo real.

La tecnología WebSocket se compone de dos elementos esenciales:

  • El Protocolo WebSocket: Define cómo se establece y mantiene la conexión, así como el formato de los mensajes intercambiados. Se estandarizó en 2011 por el IETF (Internet Engineering Task Force) bajo el RFC 6455.
  • La API WebSocket: Es la interfaz de programación que los desarrolladores utilizan para interactuar con el protocolo WebSocket en sus aplicaciones. Está incluida en el estándar HTML Living Standard y es compatible con la mayoría de los navegadores modernos, así como con diversas librerías y frameworks.

¿Para qué se Utilizan los WebSockets? Casos de Uso Clave

Las capacidades de comunicación de baja latencia de WebSocket lo hacen ideal para una amplia gama de aplicaciones en tiempo real. Algunos de los casos de uso más comunes incluyen:

  • Chats en Vivo: Permiten la interacción instantánea entre usuarios en aplicaciones de mensajería y soporte al cliente.
  • Actualizaciones de Datos en Tiempo Real: Transmiten información dinámica como resultados deportivos, precios de acciones, actualizaciones de tráfico o feeds de noticias.
  • Colaboración Multijugador: Facilitan la interacción simultánea en aplicaciones como pizarras virtuales, edición de documentos compartidos o juegos online.
  • Notificaciones y Alertas: Entregan mensajes instantáneos a los usuarios sobre eventos importantes o actualizaciones en la aplicación.
  • Sincronización en Tiempo Real Backend-Frontend: Mantienen la información consistente entre el servidor y la interfaz de usuario de una aplicación web.
  • Seguimiento de Ubicación en Vivo: Permiten rastrear la posición de usuarios o dispositivos en aplicaciones de movilidad urbana o entrega de alimentos.

¿Cómo Funcionan los WebSockets? El Proceso Detallado

Trabajar con WebSockets implica tres etapas principales:

  1. Establecimiento de la Conexión WebSocket (Handshake): El proceso comienza con un "handshake" o apretón de manos HTTP entre el cliente y el servidor. El cliente envía una solicitud HTTP especial de "upgrade" (actualización) al servidor, solicitando cambiar el protocolo HTTP a WebSocket. Si el servidor acepta, responde con un código de estado HTTP 101 "Switching Protocols", confirmando la actualización a WebSocket.
  2. Transmisión de Datos: Una vez establecido el handshake, se abre un canal de comunicación bidireccional persistente. Cliente y servidor pueden enviar y recibir mensajes (llamados "frames" o tramas) en cualquier momento, utilizando el protocolo WebSocket. Estos mensajes pueden contener datos de texto (UTF-8) o binarios.
  3. Cierre de la Conexión: Cuando la comunicación ya no es necesaria, tanto el cliente como el servidor pueden iniciar un "handshake de cierre" enviando un mensaje de cierre. Una vez que ambos extremos han intercambiado mensajes de cierre, la conexión WebSocket se considera cerrada.

Ws: La Librería WebSocket para Node.js

ws es una librería de Node.js que proporciona una implementación sencilla, rápida y robusta del protocolo WebSocket tanto para servidores como para clientes. Es una de las librerías más populares y utilizadas en el ecosistema de Node.js para trabajar con WebSockets, gracias a su rendimiento, estabilidad y facilidad de uso.

What is ws in NPM?
ws: a Node.js WebSocket library. ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and server implementation. Passes the quite extensive Autobahn test suite: server, client. Note: This module does not work in the browser.

Características Destacadas de la Librería ws:

  • Sencillez y Facilidad de Uso: Ofrece una API clara e intuitiva que facilita la creación de servidores y clientes WebSocket en Node.js.
  • Alto Rendimiento: Está diseñada para ser extremadamente rápida y eficiente, optimizando el manejo de conexiones y el procesamiento de mensajes.
  • Completamente Testeada: Supera el exhaustivo conjunto de pruebas Autobahn, garantizando su cumplimiento con los estándares WebSocket y su fiabilidad en diferentes escenarios.
  • Soporte de Estándares: Implementa las últimas versiones del protocolo WebSocket (HyBi drafts 13-17 por defecto) y borradores anteriores (HyBi drafts 07-12 opcionalmente).
  • Compresión Per-Message Deflate: Soporta la extensión permessage-deflate para comprimir los datos de los mensajes WebSocket, reduciendo el ancho de banda y mejorando el rendimiento (opcional).

Importante: La librería ws está diseñada para el backend de Node.js y no funciona en el navegador. Para aplicaciones en el navegador, se debe utilizar el objeto WebSocket nativo del navegador. Si se busca una solución que funcione tanto en Node.js como en el navegador, existen librerías wrapper como isomorphic-ws.

Optimizando el Rendimiento de ws: Módulos Opcionales

Para mejorar aún más el rendimiento de ws, se pueden instalar dos módulos opcionales:

  • bufferutil: Un addon binario que optimiza operaciones como el enmascaramiento y desenmascaramiento de la carga útil de los frames WebSocket. Se instala con: npm install --save-optional bufferutil.
  • utf-8-validate: Un polyfill binario para buffer.isUtf8(), útil en versiones antiguas de Node.js (anteriores a v18.14.0). Se instala con: npm install --save-optional utf-8-validate.

Para forzar a ws a no utilizar estos módulos, se pueden usar las variables de entorno WS_NO_BUFFER_UTIL y WS_NO_UTF_8_VALIDATE respectivamente.

What is the ws protocol?
The WebSocket protocol enables full-duplex interaction between a web browser (or other client application) and a web server with lower overhead than half-duplex alternatives such as HTTP polling, facilitating real-time data transfer from and to the server.

Compresión WebSocket con permessage-deflate en ws

ws soporta la extensión permessage-deflate, que permite negociar algoritmos de compresión entre cliente y servidor para reducir el tamaño de los mensajes WebSocket. Esta extensión está deshabilitada por defecto en el servidor y habilitada por defecto en el cliente. Activarla puede añadir una sobrecarga en términos de rendimiento y consumo de memoria, por lo que se recomienda habilitarla solo cuando sea realmente necesario. La configuración de permessage-deflate se puede realizar a través de opciones, incluyendo zlibDeflateOptions y zlibInflateOptions para personalizar los streams de compresión/descompresión de zlib.

Ejemplo de Configuración de permessage-deflate en el Servidor:

import WebSocket, { WebSocketServer } from 'ws'; const wss = new WebSocketServer({ port: 8080, perMessageDeflate: { zlibDeflateOptions: { // Opciones de zlib chunkSize: 1024, memLevel: 7, level: 3 }, zlibInflateOptions: { chunkSize: 10 * 1024 }, clientNoContextTakeover: true, serverNoContextTakeover: true, serverMaxWindowBits: 10, concurrencyLimit: 10, threshold: 1024 } }); 

Para deshabilitar la extensión en el cliente, se puede establecer la opción perMessageDeflate a false:

import WebSocket from 'ws'; const ws = new WebSocket('ws://www.host.com/path', { perMessageDeflate: false }); 

Ejemplos de Uso de la Librería ws

A continuación, se presentan algunos ejemplos de código para ilustrar el uso de la librería ws:

Enviar y Recibir Datos de Texto:

import WebSocket from 'ws'; const ws = new WebSocket('ws://www.host.com/path'); ws.on('error', console.error); ws.on('open', function open() { ws.send('algo'); }); ws.on('message', function message(data) { console.log('recibido: %s', data); }); 

Enviar Datos Binarios:

import WebSocket from 'ws'; const ws = new WebSocket('ws://www.host.com/path'); ws.on('error', console.error); ws.on('open', function open() { const array = new Float32Array(5); for (var i = 0; i < array.length; ++i) { array[i] = i / 2; } ws.send(array); }); 

Servidor Simple:

import { WebSocketServer } from 'ws'; const wss = new WebSocketServer({ port: 8080 }); wss.on('connection', function connection(ws) { ws.on('error', console.error); ws.on('message', function message(data) { console.log('recibido: %s', data); }); ws.send('algo'); }); 

Servidor HTTP/S Externo:

import { createServer } from 'https'; import { readFileSync } from 'fs'; import { WebSocketServer } from 'ws'; const server = createServer({ cert: readFileSync('/path/to/cert.pem'), key: readFileSync('/path/to/key.pem') }); const wss = new WebSocketServer({ server }); wss.on('connection', function connection(ws) { ws.on('error', console.error); ws.on('message', function message(data) { console.log('recibido: %s', data); }); ws.send('algo'); }); server.listen(8080); 

Broadcast del Servidor (Enviar Mensaje a Todos los Clientes Conectados):

import WebSocket, { WebSocketServer } from 'ws'; const wss = new WebSocketServer({ port: 8080 }); wss.on('connection', function connection(ws) { ws.on('error', console.error); ws.on('message', function message(data, isBinary) { wss.clients.forEach(function each(client) { if (client.readyState === WebSocket.OPEN) { client.send(data, { binary: isBinary }); } }); }); }); 

Preguntas Frecuentes (FAQ) sobre ws y WebSockets

¿Cómo obtener la dirección IP del cliente en ws?
La dirección IP remota del cliente se puede obtener del socket raw en el evento connection del servidor WebSocket: req.socket.remoteAddress. Si el servidor está detrás de un proxy como NGINX, la IP del cliente se puede obtener del header X-Forwarded-For.
¿Cómo detectar y cerrar conexiones rotas en WebSockets con ws?
Para detectar conexiones rotas, se puede implementar un mecanismo de "heartbeat" utilizando mensajes ping y pong. El servidor envía pings periódicamente y el cliente responde con pongs. Si el servidor no recibe un pong en un tiempo determinado, asume que la conexión está rota y la cierra.
¿Cómo conectarse a través de un proxy con ws?
Para conectarse a través de un proxy, se puede utilizar una implementación personalizada de http.Agent como https-proxy-agent o socks-proxy-agent al crear el cliente WebSocket.

Conclusión

WebSocket y la librería ws en Node.js ofrecen una poderosa combinación para construir aplicaciones web interactivas y en tiempo real. Ya sea que necesites crear un chat en vivo, transmitir datos en tiempo real o desarrollar juegos multijugador, ws proporciona las herramientas necesarias para implementar WebSockets de manera eficiente y sencilla en tus proyectos Node.js. Su robustez, rendimiento y facilidad de uso la convierten en la opción preferida por muchos desarrolladores para aprovechar al máximo el potencial de la comunicación bidireccional en la web moderna.

Subir