WebSockets é um protocolo de comunicação que permite comunicação bidirecional persistente como alternativa ao HTTP. Suponha que você queira obter atualizações para algum estado do servidor. Com HTTP, você precisaria pesquisar os dados com frequência.

Mas existem limitações para a pesquisa HTTP:

  1. As alterações nos dados não são vistas em tempo real pelos clientes inscritos
  2. O servidor responde apenas a uma solicitação inicial do cliente-em outras palavras, é unidirecional
  3. Os recursos do servidor estão vinculados às solicitações de processamento, mesmo quando não há novos dados

Com o WebSockets, os clientes não precisam pedir ao servidor novos dados, o servidor de web sockets simplesmente envia os novos dados diretamente para o cliente.

Quando você deve usar WebSockets?

WebSockets deve ser usado quando você precisa de funcionalidade em tempo real em seu aplicativo-por exemplo, um aplicativo de bate-papo ou um bot que observa o mercado de ações. WebSockets são mais usados ​​em situações em que você precisa reagir rapidamente a dados que mudam com frequência. Se os dados do seu aplicativo não mudam com frequência, pode ser melhor implementar uma lógica de pesquisa simples.

Como funciona o protocolo WebSockets?

WebSockets usam HTTP como mecanismo para iniciar uma conexão com o servidor. Essa conexão é então atualizada para uma conexão WebSocket.

Os clientes só podem acessar servidores WebSocket por meio de um esquema de URI de ws:// ou wss://. Para iniciar uma conexão WebSockets, você deve primeiro implementar um cliente WebSocket e ter um servidor WebSockets de suporte. É aí que entra Deno.

Implementando um servidor e cliente WebSocket com Deno

Aqui está o que cobriremos neste tutorial:

  1. Criação de um servidor WebSocket no Deno
  2. Criação de um cliente WebSocket no Deno
  3. Envio de mensagens entre o servidor e o cliente
  4. Transmitindo mensagens do servidor para vários clientes

1. Criação de um servidor WebSocket no Deno

Primeiro, precisamos do Deno instalado em nossas máquinas locais. Depois de fazer isso, crie um novo diretório para hospedar nosso código do servidor e do cliente:

 tutorial do websocket do mkdir

Crie um novo arquivo chamado server.ts . É aqui que criaremos um servidor HTTP simples.

 touch./server.ts

A seguir, na parte superior do arquivo, importe a função serve :

 import {serve} de"https://deno.land/[email protected]/http/server.ts";

Agora vamos criar o servidor HTTP na porta 80, que será usado para inicializar, aceitar e enviar conexões WebSocket:

 para espera (const req de serviço ({porta: 80})) {
req.response ({body:"Hello world"})
}

serve () retorna um iterável assíncrono que consiste em solicitações HTTP feitas ao nosso servidor. A sintaxe for await é usada para fazer um loop e responder a cada solicitação.

Execute o código com o seguinte comando:

 deno execute--allow-net server.ts

O parâmetro --allow-net dá permissão ao Deno para fazer chamadas de rede. Digite localhost: 80 em seu navegador e você deverá ver uma mensagem “Hello world” na página.

Em seguida, precisamos atualizar a solicitação HTTP normal para uma conexão WebSocket. Importe a função acceptWebSocket do módulo WebSocket de Deno:

 import {acceptWebSocket} de"https://deno.land/[email protected]/ws/mod.ts"

acceptWebSocket cuida da atualização da solicitação para uma conexão WebSocket. Forneceremos os parâmetros necessários:

 para espera (const req de serviço ({porta: 80})) { const {conn, r: bufReader, w: bufWriter, cabeçalhos}=req; aceitarWebSocket ({ conn, bufReader, bufWriter, cabeçalhos, }). então (handleWs)
}

Ainda não criamos a função handleWs , então vamos fazer isso antes de prosseguirmos:

 função assíncrona handleWs (sock: WebSocket) {
console.log ("soquete conectado")
para esperar (evento const de meia) {
if (evento typeof==="string"{
console.log (ev)
}
}
}

A função handleWs usa um objeto WebSocket como parâmetro. Este objeto é um iterável assíncrono que consiste em eventos emitidos pelo cliente conectado ao WebSocket. Se o evento for uma string, o evento será a carga útil da mensagem do cliente WebSocket.

Existem outros tipos de eventos, que abordaremos mais tarde. WebSockets só pode transmitir mensagens como um ArrayBuffer ou uma string, então você precisará usar JSON.stringify para transmitir mensagens JSON.

Feito isso, vamos criar o cliente WebSocket.

2. Criação de um cliente WebSocket no Deno

Crie um novo arquivo na pasta do projeto chamado client.ts :

 touch./client.ts

Definiremos uma função chamada createWebSocket , que conterá o código para inicializar um WebSocket e enviar e receber mensagens WebSocket.

 function createWebSocket () { const websocket=new WebSocket ("ws://localhost: 80") websocket.onopen=()=> { setInterval (()=> { websocket.send (`Cliente diz olá`) }, 2000) } }

Os URLs do Websocket começam com wss:// para conexões seguras ou ws:// para conexões não seguras.

Quando um objeto WebSocket é criado recentemente, sua conexão não está imediatamente pronta. Aproveitando a natureza orientada a eventos do WebSockets. podemos anexar uma função ao ouvinte de eventos WebSocket.onopen . Esta função é chamada assim que a conexão WebSocket é aberta.

Dentro da função de ouvinte de evento onopen , usamos o setInterval função para enviar uma mensagem a cada dois segundos.

Vamos testar nosso código iniciando o servidor WebSocket:

 deno execute--allow-net server.ts

E o cliente:

 deno run--allow-net client.ts

Devemos ver “Cliente diz olá” impresso no console do servidor a cada dois segundos.

3. Envio de mensagens entre o servidor e o cliente

Vimos como enviar mensagens do cliente para o servidor. Mas, como observamos acima, os WebSockets permitem mensagens bidirecionais. Vamos agora enviar mensagens do servidor para o cliente.

Atualize a função handleWs em server.ts :

 função assíncrona handleWs (sock: WebSocket) { if (! sock.isClosed) { sock.send ("Olá do servidor") }//Adicione isso para esperar (const ev de meia) { if (typeof ev==="string") { console.log (ev); } }
}

Observe que há uma verificação para detectar se o soquete já foi fechado usando a propriedade sock.isClosed .

Atualize a função createWebSocket em client.ts para receber mensagens do servidor:

 function createWebSocket () { const websocket=new WebSocket ("ws://localhost: 80") websocket.onopen=()=> { setInterval (()=> { websocket.send (`Cliente diz olá`) }, 2000) } websocket.onmessage=(mensagem)=> { console.log (mensagem.data) }
}

A execução do código atualizado deve mostrar “Hi from server” no console do cliente.

A função de ouvinte de evento onmessage é usada para assinar mensagens enviadas do servidor WebSocket. Sua carga útil está dentro da propriedade de dados.

4. Transmitindo mensagens do servidor para vários clientes

Vimos como enviar mensagens do servidor para um único cliente, mas isso raramente é útil; em um aplicativo de bate-papo, por exemplo, você precisaria transmitir uma mensagem para vários clientes instantaneamente. Também pode ser necessário diferenciar uma conexão WebSocket de outra.

No topo do nosso arquivo server.ts , vamos criar um objeto Map e atribuir a ele a variável sockets :

 const sockets=new Map  ()

Um Map é um objeto com métodos que envolvem um par de valores-chave. Nesse caso, associamos uma string a um objeto WebSockets. Armazenaremos todas as conexões WebSockets na variável sockets .

Agora atualize a função handleWs :

 função assíncrona handleWs (sock: WebSocket) { console.log ('conectado') const uid=v4.generate () sockets.set (uid, meia) para esperar (const ev de meia) { if (isWebSocketCloseEvent (ev)) { sockets.delete (uid) Retorna } if (typeof ev==="string") { console.log (ev) broadcastMessage (ev, uid) } }
}

Importe a função v4.generate da biblioteca uuid :

 import {v4} de'https://deno.land/std/uuid/mod.ts';

A função v4.generate gera um ID aleatório para cada conexão WebSocket. Cada ID é usado para identificar uma conexão WebSocket ao enviar uma mensagem. Vamos adicionar essa conexão à variável sockets .

Observe que removemos as conexões WebSocket assim que ocorre o evento de fechamento:

 if (isWebSocketCloseEvent (ev)) { sockets.delete (uid) Retorna
}

A seguir, criaremos uma função chamada broadcastMessage , que recebe uma mensagem como parâmetro para transmissão a todos os WebSockets armazenados na variável sockets :

 função broadcastMessage (mensagem: string, uid: string) { sockets.forEach ((socket)=> { if (! socket.isClosed && uid!==id) socket.send (mensagem) })
}

Observe que usamos um segundo parâmetro, uid , para identificar o cliente que está enviando a mensagem. Observe a verificação uid!==id , que garante que não transmitamos uma mensagem para seu soquete de origem.

Agora vamos atualizar nosso arquivo client.ts para simular vários clientes conectando e enviando mensagens. Atualize a função createWebsocket para obter um parâmetro id :

 function createWebSocket (id: number) { const websocket=new WebSocket ("ws://localhost: 80") websocket.onopen=()=> { setInterval (()=> { websocket.send (`Cliente $ {id} diz olá`) }, 2.000 * id) } websocket.onmessage=(mensagem)=> { console.log (`Cliente $ {id}: $ {message.data}`) }
}

Observe o valor do argumento setInterval 2000 * id . Como estamos passando números como IDs, um ID de 1 esperaria 2.000 ms (ou seja, 2s) para enviar uma mensagem, enquanto um ID de 4 esperaria 8.000 ms (ou seja, 8s).

Criamos várias conexões WebSocket usando um loop for :

 para (deixe x=1; x <10; x ++) { createWebSocket (x)
}

Quando executamos server.ts e client.ts , devemos ver mensagens como esta:

 Cliente 3: Cliente 8 diz olá
Cliente 4: o cliente 8 diz olá
Cliente 6: o cliente 8 diz olá

Conclusão

O protocolo WebSockets fornece uma maneira de se comunicar bidirecionalmente sem polling. O WebSockets deve ser usado para aplicativos em tempo real, como visualização do mercado de ações e aplicativos de mensagens que exigem feedback instantâneo.

Usar WebSockets para aplicativos com dados que não mudam com frequência seria um exagero e, como tal, um mecanismo simples de pesquisa HTTP seria preferível. O código completo para este tutorial pode ser encontrado no repo aqui .

A postagem Usando WebSockets com Deno apareceu primeiro em LogRocket Blog .

Source link