Lección 13: WebSockets
A diferencia de Fetch data o AJAX, el API de WebSocket es una tecnología avanzada que nos permite la comunicación bidireccional entre un cliente y un servidor. El servidor puede enviar mensajes al cliente y el cliente al servidor por el mismo camino.

Esta tecnología es indispensable para hacer tareas como:
- Aplicaciones en tiempo real, como un Chat o una red social.
- Envío de mensajes a un cliente específico, como unas notificaciones.
- Envío de mensajes masivos, como un videojuego multijugador.
- Aplicaciones de colaboración, como Google Drive o Notion.
Servidor
Para ilustrar las funcionalidades de WebSocket sin recurrir a servicios complejos o de pago, crearemos un pequeño servidor. Esta lección no aspira a enseñar backend con JavaScript o ahondar en Node, sino ofrecer una elemental herramienta para aprender WebSockets.
Crearemos un servidor que devolverá cualquier información enviada a todos clientes conectados (Broadcast).

Primero nos aseguramos que disponemos de Node.js (binario para la ejecución de JavaScript) y npm (gestor de paquetes JavaScript) instalado en el equipo.
node --version
npm --version
En ambos casos nos enseñará la versión instalada. En caso contraría mostrará un error que deberemos arreglar antes de continuar.
Ahora instalaremos las bibliotecas de WebSockets.
Nos situamos sobre una carpeta nueva, para no mezclar con otros trabajos, y ejecutaremos.
npm install ws
Creamos un archivo llamado index.js, donde nos encontramos situados, y pega el siguiente código.
// Importaciones
const WebSocket = require("ws");
const http = require("http");
// Creamos una instacia del servidor HTTP (Web)
const server = http.createServer();
// Creamos y levantamos un servidor de WebSockets a partir del servidor HTTP
const wss = new WebSocket.Server({ server });
// Escuchamos los eventos de conexión
wss.on("connection", function connection(ws) {
// Escuchamos los mensajes entrantes
ws.on("message", function incoming(data) {
// Iteramos todos los clientes que se encuentren conectados
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
// Enviamos la información recibida
client.send(data.toString());
}
});
});
});
// Levantamos servidor HTTP
server.listen(8080);
console.log("Servidor funcionando. Utiliza ws://localhost:8080 para conectar.")
Guardamos.
Ahora levantaremos el servidor
node index.js
¡Listo! Para conectarnos con el cliente usaremos ws://localhost:8080. Lo dejamos funcionando y pasamos a crear un cliente.
Cliente
Conectar

Nativamente disponemos de un API para realizar las interacciones. Necesitaremos usar el objeto WebSocket y guardarlo en una variable para utilizar sus eventos o funcionalidades.
const miWebSocket = new WebSocket(url [, protocolos]);
Puede ser utilizado incluyendo el protocolo junto a la ruta completa .
const miWebSocket = new WebSocket("ws://miservidor.com");
O separando los protocolos a utilizar como segundo argumento.
const miWebSocket = new WebSocket("miservidor.com", ["ws", "wss"]);
Al igual que existe una diferencia entre http y https, siendo el último seguro, en el protocolo de WebSockets también nos la encontraremos.
- ws: WebSockets.
- wss: WebSockets seguro.
const miWebSocket = new WebSocket("ws://miservidor.com");
Siendo más seguro.
const miWebSocket = new WebSocket("wss://miservidor.com");
Además dispondremos de un evento que será lanzado al conectar.
const miWebSocket = new WebSocket("wss://miservidor.com");
function open () {
// Abre conexión
console.log("WebSocket abierto.");
}
miWebSocket.addEventListener("open", open);
Mensajes

Escuchar
Si queremos recoger los mensajes enviados por el servidor, u otros clientes, debemos estar atentos al evento message.
const miWebSocket = new WebSocket("wss://miservidor.com");
function message (evento) {
// Se recibe un mensaje
console.log("WebSocket ha recibido un mensaje");
// Mostrar mensaje en HTML
misRespuestas.innerHTML = misRespuestas.innerHTML.concat(evento.data, "<br>");
}
miWebSocket.addEventListener("message", message);
Emitir
Para enviar mensajes al servidor disponemos de la función send().
const miWebSocket = new WebSocket("wss://miservidor.com");
miWebSocket.send("Mi mensaje");
Gestión de errores
No siempre irá todo como esperamos, puede existir cortes de conexión por caídas de la red o problemas en el servidor.

Par ello estaremos alerta del evento error.
const miWebSocket = new WebSocket("wss://miservidor.com");
function error (evento) {
// Ha ocurrido un error
console.error("WebSocket ha observado un error: ", evento);
}
miWebSocket.addEventListener("error", error);
Desconectar
Para la situación en que se desconecte el cliente o se rompa la conexión, posiblemente por un fallo importante, capturaremos el evento close.

const miWebSocket = new WebSocket("wss://miservidor.com");
function close () {
// Cierra la conexión
console.log("WebSocket cerrado.");
}
miWebSocket.addEventListener("close", close);
Ejemplo
Con todo lo aprendido conectaremos con el servidor para enviar o recibir mensajes.
Crea un archivo llamado cliente-ws.html con el siguiente contenido.
<!doctype html>
<html lang="es">
<head>
<meta charset="UTF-8"/>
<title>Ejemplo cliente de WebSocket</title>
</head>
<body>
<!-- Nuevo Mensaje -->
<input type="text" id="nuevo-mensaje">
<!-- Mensajes recibidos -->
<div id="respuestas"></div>
<script>
// Variables
const miWebSocket = new WebSocket("ws://localhost:8080");
const miNuevoMensaje = document.querySelector("#nuevo-mensaje");
const misRespuestas = document.querySelector("#respuestas");
// Funciones
function open () {
// Abre conexión
console.log("WebSocket abierto.");
}
async function message (evento) {
// Se recibe un mensaje
console.log("WebSocket ha recibido un mensaje");
// Mostrar mensaje en HTML
const mensajeRecibido = await evento.data.text(); // Arreglo para Node ya que devuelve Blob. Solo con "evento.data" debería ser suficiente
misRespuestas.innerHTML = misRespuestas.innerHTML.concat(mensajeRecibido, "<br>");
}
function error (evento) {
// Ha ocurrido un error
console.error("WebSocket ha observado un error: ", evento);
}
function close () {
// Cierra la conexión
console.log("WebSocket cerrado.");
}
function enviarNuevoMensaje (evento) {
// Evento tecla Enter
if(evento.code === "Enter") {
// Envia mensaje por WebSockets
miWebSocket.send(miNuevoMensaje.value);
// Borra texto en el input
miNuevoMensaje.value = "";
}
}
// Eventos de WebSocket
miWebSocket.addEventListener("open", open);
miWebSocket.addEventListener("message", message);
miWebSocket.addEventListener("error", error);
miWebSocket.addEventListener("close", close);
// Evento para envia nuevo mensaje
miNuevoMensaje.addEventListener("keypress", enviarNuevoMensaje);
</script>
</body>
</html>
Abre el archivo con diferentes ventanas al mismo tiempo para ver su funcionamiento.
Actividad 1
Crea un input de texto para enviar notificaciones a todos los que estén conectados. Utiliza el servidor de ejemplo de la lección.

Nivel pesadilla 👹
Añade un sonido de alerta cuando recibas un nuevo mensaje.
Actividad 2
Construye un sencillo y liviano Chat. Utiliza el servidor de ejemplo de la lección.
Nivel pesadilla 👹
Lamentablemente cuando refrescamos la página se pierden los mensajes. Soluciona el problema almacenando cada mensaje en un Localstorage y obteniendo todos al entrar.
Actividad 3
Programa un juego de 3 en raya para jugar con un amigo en remoto. Utiliza el servidor de ejemplo de la lección.
Esta obra está bajo una Licencia Creative Commons Atribución-NoComercial-SinDerivadas 4.0 Internacional.
¿Me invitas a un café? ☕
Puedes hacerlo usando el terminal.
ssh customer@andros.dev -p 5555
Comentarios
Nuevo comentario
Nueva replica {{ formatEllipsisAuthor(replyComment.author) }}
Escribe el primer comentario
{{ comments.length }} comentarios