Como usar o Websocket com uma API Express simples?

Breve descrição da tecnologia



Websocket é um protocolo de comunicação através de uma conexão TCP, projetado para trocar mensagens entre um navegador e um servidor web em tempo real.



O cliente e o servidor usam um protocolo semelhante ao HTTP para estabelecer uma conexão WebSocket. O cliente faz uma solicitação HTTP especial à qual o servidor responde de uma maneira específica.



Comentários



Embora as novas solicitações e respostas sejam "semelhantes" às solicitações e respostas HTTP, não são. Por exemplo, uma solicitação tem um corpo, mas não há nenhum campo "Content-Length" nos cabeçalhos (o que viola as convenções HTTP). Você pode ler mais sobre isso na Wikipedia .



Uma das principais vantagens da tecnologia é a sua simplicidade. Existem apenas 4 eventos no cliente e servidor para processar:



  1. conexão
  2. erro
  3. mensagem
  4. perto


Por que Websocket?



Além do ws, existem dois outros métodos de transmissão contínua de dados: Eventos enviados pelo servidor (SSE) e Long Polling.



Vamos comparar os mecanismos de comunicação contínua entre o servidor e o cliente, e também tirar conclusões sobre porque vale (ou não vale) usar um websocket.



Websocket sse longa piscina
protocolo websocket (ws ou wss) HTTP (S) HTTP (S)
Rapidez Alto baixo baixo
direcionalidade de fluxos de dados bidirecional unidirecional bidirecional
Além disso transferência de dados binários, não

há suporte para alguns navegadores antigos
reconexão automática quando a conexão é interrompida


Uma das principais vantagens da tecnologia ws é a velocidade de transferência de dados. SSE e LP usam o protocolo HTTP (S) e funcionam da seguinte forma:



  1. Fazer um pedido de mudanças;
  2. Se alterações aparecerem no servidor, o servidor as enviará;
  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"))


O que está acontecendo aqui?



Para criar um servidor que suporte ws, criamos um servidor http regular e, em seguida, vinculamos um servidor a ele ao criar um websocket.



A função “on” ajuda a gerenciar eventos de websocket. O evento mais notável é o evento de mensagem, então vamos dar uma olhada nele.



Aqui a função recebe o parâmetro m - a mensagem, ou seja, o que o usuário enviou. Assim, podemos enviar uma string do cliente e processá-la no servidor. Nesse caso, o servidor simplesmente encaminha esta mensagem para todos os conectados ao servidor websocket. A matriz de clientes do objeto webSocketServer contém todas as conexões com o servidor. O objeto ws armazena apenas uma conexão por vez.



Comente



Você não deve usar essa abordagem em um aplicativo real. Se a API for descrita dessa forma, o servidor não poderá distinguir uma solicitação da outra. Como você pode construir uma API baseada em websocket será escrito mais tarde.



A interação com o servidor no cliente será assim:



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 baseada em Websocket



Ao contrário da API REST, em que as solicitações são distribuídas em diferentes urls, a API Websocket tem apenas um url. Para construir uma API completa baseada em websockets, você precisa ensinar o sistema a distinguir uma solicitação de outra. Isso pode ser implementado da seguinte forma:



1) Do cliente, transmitiremos solicitações na forma de uma string json, que analisaremos no servidor:



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


2) No servidor, analisamos a string e selecionamos o campo do evento - o tipo de solicitação. Vamos escrever a resposta correspondente 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);
   }
}


Assim, podemos enviar diferentes solicitações para o servidor e processar a resposta dependendo da solicitação.



Conclusão



Se você recebeu a tarefa de fazer uma API e descobriu que o cliente não está interessado em suportar navegadores antigos, uma API baseada em WebSocket é uma excelente escolha. Para sua comodidade, preparamos o código para as partes cliente e servidor no link .



All Articles