WebSockets: qué son y cómo funcionan
Cuando tienes que desarrollar aplicaciones que implementan comunicaciones en tiempo real, los WebSockets son una tecnología imprescindible. Te explicamos cómo funcionan, su papel en aplicaciones como chats en vivo o juegos online y cómo implementar esta tecnología en distintos lenguajes.
¿Qué son los WebSockets?
Los WebSockets son uno de los mecanismos disponibles en la web para enviar información entre sistemas informáticos. Es una tecnología de desarrollo web mucho más utilizada de lo que podría parecer y por supuesto, es ampliamente soportada por los navegadores.
Hay dos características fundamentales que distinguen los WebSockets de otros modelos de comunicación:
- Las conexiones entre el cliente y el servidor son bidireccionales por lo que ambos sistemas pueden transferir información en cualquier sentido.
- Las conexiones además son persistentes, por lo que no necesitan iniciarse o pararse después de enviar o recibir la información.
Estas características los hacen fundamentales en las aplicaciones en tiempo real, como los chats o los juegos online, pero también ante cualquier aplicación de monitorización que reciba y muestre datos constantemente, como las aplicaciones de mercados financieros.
Diferencia entre WebSockets y HTTP tradicional
Las comunicaciones de manera tradicional en la web se realizan mediante HTTP. Este es el protocolo que usa el navegador para recibir los datos de una página web, como el código HTML, las imágenes, CSS, etc.
Las características de WebSockets optimizan la transferencia de datos en aplicaciones interactivas y en tiempo real, gracias a estas diferencias que presenta con respecto a HTTP.
- Temporalidad de las conexiones: Las conexiones HTTP se abren y se cierran para cualquier transferencia, mientras que las conexiones WebSockets son permanentes, por lo que no requieren cerrarse en cada transferencia, lo que las hace más rápidas.
- Sentido de la transferencia: Las conexiones HTTP usan un mecanismo mediante el cual el cliente debe solicitar un recurso y como consecuencia el servidor se lo envía. Es el cliente por tanto el que debe iniciar la comunicación. En WebSockets la conexión es bidireccional en todo momento, tanto el cliente puede enviar datos al servidor en cualquier momento, como el servidor puede enviarlos al cliente sin que éste haya requerido abrir una conexión.
¿Cómo funcionan los WebSocket? ¿Cuál es su estructura?
Los mecanismos de WebSockets también son un poco distintos de los más conocidos de HTTP. Vamos a resumirlos sin entrar en demasiados aspectos técnicos que a decir verdad son transparentes en la mayoría de los casos para los desarrolladores.
Características principales del protocolo WebSocket
Las características principales ya las hemos mencionado. Se resume en una comunicación bidireccional y persistente. Esto da como resultado una latencia sensiblemente menor que en HTTP, pero también un consumo de recursos más reducido.
¿Cómo se establece una conexión WebSocket?
Como todo protocolo, WebSocket tiene una serie de pasos en sus comunicaciones.
- La comunicación comienza con una solicitud HTTP de tipo «Handshake» en el que figura un encabezado específico: «Upgrade: websocket».
- Luego debe darse una aceptación del servidor, si es que soporta WebSockets. En ese caso responde con un código de estado 101 Switching Protocols.
- Una vez tenemos el canal abierto se establece la conexión bidireccional, lo que significa que ambas partes pueden intercambiar mensajes en cualquier momento.
Formato de los mensajes en WebSockets
Los mensajes en WebSockets pueden enviarse tanto en el formato de texto (Con codificación UTF-8), lo que puede dar pie a transferencias de textos o datos estructurados en formato JSON o cualquier otro.
Pero además soportan también el formato binario, lo que puede ser útil para transferir archivos o streams de datos en crudo.
Estados de la conexión en WebSocket
Finalmente, conviene saber que un WebSocket puede encontrarse en cuatro estados diferentes:
- CONNECTING: Cuando la conexión está en proceso de establecimiento.
- OPEN: Que se da cuando la conexión está activa y lista para el intercambio de mensajes.
- CLOSING: Cuando la conexión está en proceso de cierre.
- CLOSED: Que indica que la conexión ha sido cerrada.
¿Para qué se utiliza WebSocket?
Ya hemos adelantado algunos usos típicos de las conexiones por WebSockets, pero vamos a ampliar un poco esta información.
Aplicaciones en tiempo real
Debido a las actualizaciones instantáneas y la baja latencia de la tecnología de WebSockets es posible usarla para implementar aplicaciones que requieran datos en tiempo real, como chats en vivo o paneles de monitorización de datos.
Actualizaciones en vivo
Cuando necesitamos que un componente se actualice en vivo, mostrando continuamente cambios, como por ejemplo la cotización de las acciones o del mercado de divisas, los WebSockets son la tecnología más adecuada para trabajar.
Juegos online
Los juegos online también requieren el trasiego de datos con el que actualizar a los jugadores en todo momento. Estas comunicaciones deben ser en tiempo real y con poca latencia. Además deben poder realizarse en las dos direcciones. Es por ello que muchos juegos multijugador en línea utilizan WebSockets.
Streaming de audio y video
El protocolo WebSocket también es útil para la transmisión de streams de datos en tiempo real, algo ideal para la transmisión de audio y vídeo.
Implementación de WebSockets en distintos lenguajes
Ahora vamos a ver algunas alternativas de tecnologías para la implementación de aplicaciones que hagan uso de WebSockets.
Primero hay que decir que si deseas implementar WebSockets para una aplicación web en la parte del cliente deberás usar Javascript, que es el lenguaje que se puede ejecutar en el navegador.
Luego, para la parte del servidor puedes usar distintos stacks de tecnologías. Estas son las más habituales.
WebSockets en JavaScript con Node.js
En Node.js recomendamos implementar servidores de WebSockets con la biblioteca «ws», que resulta especialmente útil, moderna y sencilla de usar.
Un «Hola Mundo» en el uso de WebSockets con ws sería algo como esto:
const WebSocket = require('ws'); const server = new WebSocket.Server({ port: 8080 }); server.on('connection', ws => { ws.on('message', message => { console.log(`Mensaje recibido: ${message}`); }); ws.send('Conexión establecida'); });
Uso de WebSockets en Python con Flask y Django
Si estás en Python te recomendamos usar alguna de las bibliotecas disponibles en tu framework de desarrollo. Si estás en Flask te recomendamos usar Flask-SocketIO y en el caso que uses Django tendrás que mirar Django Channels.
Implementación en PHP y otros lenguajes
En PHP también se pueden implementar de una manera sencilla los WebSockets. La solución más común en PHP sería la biblioteca Ratchet. Ahora bien, si usas algún framework PHP te recomendamos ver si existe alguna implementación de WebSockets que se integre mejor con él. Por ejemplo, si estás en Laravel lo mejor sería usar Laravel Reverb.
Por supuesto, otros lenguajes de Backend también soportan WebSockets con sus correspondientes librerías. Por ejemplo en Java te recomendamos javax.websocket.
Buenas prácticas de seguridad en WebSockets
Para acabar vamos a repasar algunos consejos importantes si piensas implementar alguna solución basada en WebSockets.
Uso de WebSockets sobre SSL/TLS (WSS)
El uso de WebSockets es recomendado que se realice mediante protocolos seguros como SSL/TLS. Esto permitirá que usemos «secure WebSocket protocol» (WSS), lo que evitará potenciales ataques de interceptación de datos.
Prevención de ataques como Cross-Site WebSocket Hijacking
Otro tipo de ataques sería el Cross-Site WebSocket Hijacking o secuestro de WebSockets. Para evitarlos es importante validar el origen de las conexiones y restringir el acceso mediante encabezados como Origin y Sec-WebSocket-Origin.
Autenticación y autorización en conexiones WebSocket
Para garantizar que solo usuarios autorizados puedan acceder a sus propios datos en las comunicaciones por WebSocket se utilizan generalmente tokens (JWT). Aunque en casos donde trabajes con cookies de sesión también podrías usarlas técnicamente, no es tan frecuente.
Los token de autenticación funcionan de manera similar a los usados en servicios web o APIs, a los que accedemos mediante código frontend. Por ejemplo los puedes enviar en los encabezados de la autenticación en el handshake, o una vez establecida la conexión mediante un mensaje de autenticación en el que figure el token.