Lección 13: WebSockets

A diferencia de 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.

AJAX vs WebSockets

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 Back-End 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).

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);
            }
        });
    });
});

// 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

Conectar WebSocket

Nativamente disponemos de un API para realizar las interacciones.

const miWebSocket = new WebSocket(url [, protocolos]);

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

Enviar mensaje con WebSocket

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.

Error con WebSocket

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.

Desconectar WebSocket

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.");
      }

      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>');
      }

      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.

13-1 13-2 13-3

¿Te ayudo?

  • 1 café: ¡Gracias por el apoyo! Te ayudo a que esta web siga estando online pagando los servidores.
  • 2 cafés: Respondo a una duda en los comentarios.
  • 4 cafés: Te corrijo una actividad y te envío feedback.
Comprame un café

Comentarios

{{ comments.length }} comentarios

Nuevo comentario

Nueva replica  {{ formatEllipsisAuthor(replyComment.author) }}

Acepto la política de Protección de Datos.

Escribe el primer comentario