¿Cómo usar Websocket con una API Express simple?

Breve descripción de la tecnología



Websocket es un protocolo de comunicación a través de una conexión TCP, diseñado para intercambiar mensajes entre un navegador y un servidor web en tiempo real.



Para establecer una conexión WebSocket, el cliente y el servidor utilizan un protocolo similar a HTTP. El cliente realiza una solicitud HTTP especial a la que el servidor responde de una manera específica.



Comentarios



Aunque las nuevas solicitudes y respuestas son "similares" a las solicitudes y respuestas HTTP, no lo son. Por ejemplo, una solicitud tiene un cuerpo, pero no hay un campo "Longitud de contenido" en los encabezados (que viola las convenciones HTTP). Puede leer más sobre esto en Wikipedia .



Una de las principales ventajas de la tecnología es su sencillez. Solo hay 4 eventos en el cliente y el servidor para procesar:



  1. conexión
  2. error
  3. mensaje
  4. cerca


¿Por qué Websocket?



Además de ws, existen otros dos métodos de transmisión continua de datos: eventos enviados por el servidor (SSE) y sondeo largo.



Comparemos los mecanismos de comunicación continua entre el servidor y el cliente, y también saquemos conclusiones sobre por qué vale (o no) utilizar un websocket.



Websocket sse larga agrupación
protocolo websocket (ws o wss) HTTP (S) HTTP (S)
velocidad alto bajo bajo
direccionalidad de los flujos de datos bidireccional unidireccional bidireccional
Adicionalmente transferencia de datos binarios, no

hay soporte para algunos navegadores antiguos
reconexión automática cuando se rompe la conexión


Una de las principales ventajas de la tecnología ws es la velocidad de transferencia de datos. SSE y LP usan el protocolo HTTP (S) y funcionan de esta manera:



  1. Hacer una solicitud de cambios;
  2. Si aparecen cambios en el servidor, el servidor los envía;
  3. , .


:



  1. .
  2. , HTTP(S).
  3. , .


api.



const http = require("http");
const express = require( "express");
const WebSocket = require( "ws");

const app = express();

const server = http.createServer(app);

const webSocketServer = new WebSocket.Server({ server });

webSocketServer.on('connection', ws => {
   ws.on('message', m => {
webSocketServer.clients.forEach(client => client.send(m));
   });

   ws.on("error", e => ws.send(e));

   ws.send('Hi there, I am a WebSocket server');
});

server.listen(8999, () => console.log("Server started"))


¿Que está pasando aqui?



Para crear un servidor que admita ws, creamos un servidor http normal y luego le vinculamos un servidor al crear un websocket.



La función "on" ayuda a administrar los eventos de websocket. El evento más notable es el evento del mensaje, así que echémosle un vistazo más de cerca.



Aquí la función recibe el parámetro m - el mensaje, es decir, lo que envió el usuario. Por lo tanto, podemos enviar una cadena desde el cliente y procesarla en el servidor. En este caso, el servidor simplemente reenvía este mensaje a todas las personas conectadas al servidor websocket. La matriz de clientes del objeto webSocketServer contiene todas las conexiones al servidor. El objeto ws solo almacena una conexión a la vez.



Comentario



No debería utilizar este enfoque en una aplicación real. Si describe la API de esta manera, entonces el servidor no puede distinguir una solicitud de otra. Más adelante se escribirá cómo puede crear una api basada en websocket.



La interacción con el servidor en el cliente se verá así:



export const wsConnection = new WebSocket("ws://localhost:8999");
wsConnection.onopen = function() {
    alert(" .");
};

wsConnection.onclose = function(event) {
    if (event.wasClean) {
        alert('  ');
    } else {
        alert(' '); // , ""  
    }
    alert(': ' + event.code + ' : ' + event.reason);
};

wsConnection.onerror = function(error) {
    alert(" " + error.message);
};

export const wsSend = function(data) {
// readyState - true,   
    if(!wsConnection.readyState){
        setTimeout(function (){
            wsSend(data);
        },100);
    } else {
        wsConnection.send(data);
    }
};


API basada en Websocket



A diferencia de la API REST, donde las solicitudes se distribuyen a través de diferentes URL, la API de Websocket solo tiene una URL. Para crear una API completa basada en websockets, debe enseñar al sistema a distinguir una solicitud de otra. Esto se puede implementar de la siguiente manera:



1) Desde el cliente, transmitiremos solicitudes en forma de una cadena json, que analizaremos en el servidor:



const sendMessage = (message) => conn.send(JSON.stringify({ event: "chat-message", payload: { userName, message }}));


2) En el servidor, analizamos la cadena y seleccionamos el campo del evento: el tipo de solicitud. Anotemos la respuesta correspondiente para cada tipo:



const dispatchEvent = (message, ws) => {
   const json = JSON.parse(message);
   switch (json.event) {
       case "chat-message": webSocketServer.clients.forEach(client => client.send(message));
       default: ws.send((new Error("Wrong query")).message);
   }
}


Así, podemos enviar diferentes solicitudes al servidor y procesar la respuesta en función de la solicitud.



Conclusión



Si se le asignó la tarea de crear una API y descubrió que el cliente no está interesado en admitir navegadores antiguos, una API basada en WebSocket es una excelente opción. Para su comodidad, hemos preparado el código para las partes del cliente y del servidor en el enlace .



All Articles