O que são Websockets?

Nos últimos anos, um novo tipo de comunicação começou a surgir na web e em aplicações móveis, chamadas websockets. Este protocolo foi há muito esperado e foi finalmente padronizado pela IETF em 2011, abrindo caminho para uma utilização generalizada.

Este novo protocolo abre uma linha de comunicação muito mais rápida e eficiente para o cliente. Tal como o HTTP, os websockets funcionam sobre uma ligação TCP, mas são muito mais rápidos porque não temos de abrir uma nova ligação para cada vez que queremos enviar uma mensagem, uma vez que a ligação é mantida viva durante o tempo que o servidor ou cliente quiser.

P>Even melhor, uma vez que a ligação nunca morre temos finalmente uma comunicação full-duplex disponível para nós, o que significa que podemos empurrar dados para o cliente em vez de termos de esperar que eles peçam dados ao servidor. Isto permite que os dados sejam comunicados para trás e para a frente, o que é ideal para coisas como aplicações de chat em tempo real, ou mesmo jogos.

Como funcionam os Websockets?

No seu núcleo, um Websocket é apenas uma ligação TCP que permite uma comunicação full-duplex, o que significa que um lado da ligação pode enviar dados para o outro, mesmo ao mesmo tempo.

Para estabelecer esta ligação, o protocolo inicia efectivamente o aperto de mão como um pedido HTTP normal, mas depois é “actualizado” usando o cabeçalho HTTP de pedido de actualização, como isto:

O servidor envia então uma resposta HTTP 101 “Switching Protocols”, reconhecendo que a ligação vai ser actualizada. Uma vez feita esta ligação, muda para um protocolo binário bidireccional, altura em que os dados da aplicação podem ser enviados.

Tudo o que o protocolo tem de fazer para manter a ligação aberta é enviar alguns pacotes ping/pong, o que diz ao outro lado que eles ainda lá estão. Para fechar a ligação, um simples pacote de “ligação fechada” é enviado.

alguns exemplos de Websocket

Das muitas bibliotecas de Websocket diferentes para Node.js disponíveis para nós, optei por usar socket.io ao longo deste artigo porque parece ser o mais popular e é, na minha opinião, o mais fácil de usar. Embora cada biblioteca tenha a sua própria API única, elas também têm muitas semelhanças, uma vez que estão todas construídas sobre o mesmo protocolo, por isso espero que consiga traduzir o código abaixo para qualquer biblioteca que queira utilizar.

Para o servidor HTTP, estarei a utilizar o Express, que é o servidor de Nodo mais popular por aí. Tenha em mente que também pode usar o módulo http simples se não precisar de todas as funcionalidades do Express. Embora, uma vez que a maioria das aplicações irá utilizar o Express, é o que também iremos utilizar.

Note: Ao longo destes exemplos removi grande parte do código da placa de caldeira, pelo que alguns deste código não irão funcionar fora da caixa. Na maioria dos casos pode referir-se ao primeiro exemplo para obter o código da chapa de caldeira.

Estabelecer a Ligação

Para que uma ligação seja estabelecida entre o cliente e o servidor, o servidor deve fazer duas coisas:

  1. Ligue-se ao servidor HTTP para tratar as ligações websocket
  2. Serve o socket.io.js biblioteca cliente como um recurso estático

No código abaixo, pode ver o item (1) a ser feito na 3ª linha. O item (2) é feito para si (por defeito) pelo socket.io biblioteca e é servido no caminho https://stackabuse.com/socket.io/socket.io.js. Por defeito, todas as ligações e recursos da web são servidos dentro do /socket.io caminho.

Servidor

O cliente também precisa de fazer duas coisas:

  1. Carregar a biblioteca a partir do servidor
  2. Li> Chamada .connect() para o endereço do servidor e o caminho do websocket

Cliente

<script src="https://stackabuse.com/socket.io/socket.io.js"></script><script> var socket = io.connect('/');</script>

Se navegar no seu navegador para e inspeccionar os pedidos HTTP nos bastidores utilizando as ferramentas de desenvolvimento do seu navegador, deverá poder ver o aperto de mão a ser executado, incluindo os pedidos GET e a resposta resultante aos Protocolos de Comutação HTTP 101.

Enviar Dados do Servidor para o Cliente

Okay, agora para algumas das partes mais interessantes. Neste exemplo vamos mostrar-lhe a forma mais comum de enviar dados do servidor para o cliente. Neste caso, estaremos a enviar uma mensagem a um canal, que pode ser subscrito e recebido pelo cliente. Assim, por exemplo, uma aplicação cliente pode estar a ouvir no canal ‘anúncios’, que conteria notificações sobre eventos em todo o sistema, como quando um utilizador entra numa sala de chat.

p>No servidor, isto é feito esperando que a nova ligação seja estabelecida, depois chamando o métodosocket.emit()para enviar uma mensagem a todos os clientes ligados.

Servidor

io.on('connection', function(socket) { socket.emit('announcements', { message: 'A new user has joined!' });});

Cliente

Enviar dados do cliente para o servidor

Mas o que faríamos quando quiséssemos enviar dados de outra forma, de cliente para servidor? É muito semelhante ao último exemplo, utilizando os métodos socket.emit() e socket.on().

Servidor

Cliente

Contagem de Utilizadores Ligados

Este é um bom exemplo a aprender uma vez que mostra mais algumas características de socket.io (como o disconnect evento), é fácil de implementar, e é aplicável a muitos webapps. Vamos utilizar o connection e disconnect eventos para contar o número de utilizadores activos no nosso sítio, e vamos actualizar todos os utilizadores com a contagem actual.

Servidor

Cliente

Uma forma muito mais simples de rastrear a contagem de utilizadores no servidor seria simplesmente usar isto:

var numClients = io.sockets.clients().length;

Mas aparentemente existem alguns problemas em torno disto, pelo que poderá ter de se manter a par da contagem de clientes.

Rooms and Namespaces

As chances são à medida que a sua aplicação cresce em complexidade, necessitará de mais personalização com os seus websockets, como enviar mensagens a um utilizador específico ou conjunto de utilizadores. Ou talvez deseje uma separação rigorosa da lógica entre as diferentes partes da sua aplicação. É aqui que salas e namespaces entram para jogar.

Nota: Estas características não fazem parte do protocolo websocket, mas adicionadas no topo por socket.io.

Por defeito, socket.io utiliza o namespace raiz (/) para enviar e receber dados. Programmaticamente, pode aceder a este namespace através de io.sockets, embora muitos dos seus métodos tenham atalhos em io. Assim, estas duas chamadas são equivalentes:

io.sockets.emit('stats', { data: 'some data' });io.emit('stats', { data: 'some data' });

Para criar o seu próprio namespace, tudo o que tem de fazer é o seguinte:

Também, o cliente tem de se ligar explicitamente ao seu namespace:

<script src="https://stackabuse.com/socket.io/socket.io.js"></script><script> var socket = io('/stackabuse');</script>

Agora quaisquer dados enviados dentro deste namespace serão separados do namespace padrão / namespace, independentemente do canal utilizado.

indo ainda mais longe, dentro de cada espaço de nomes pode entrar e sair de ‘salas’. Estas salas proporcionam outra camada de separação no topo dos namespace, e uma vez que um cliente só pode ser adicionado a uma sala do lado do servidor, proporcionam também alguma segurança extra. Assim, se quiser ter a certeza de que os utilizadores não estão a bisbilhotar certos dados, pode usar uma sala para os esconder.

Para ser adicionado a uma sala, deve .join() it:

io.on('connection', function(socket){ socket.join('private-message-room');});

Então, a partir daí pode enviar mensagens a todos os que pertencem à sala em questão:

io.to('private-message-room').emit('some event');

E finalmente, ligue .leave() para deixar de receber mensagens de eventos de uma sala:

socket.leave('private-message-room');

Conclusion

Esta é apenas uma biblioteca que implementa o protocolo websockets, e há muitas mais lá fora, todas com as suas próprias características e pontos fortes únicos. Aconselho a experimentar algumas das outras (como por exemplo, os websockets com aceno de cabeça) para se ter uma ideia do que há por aí.

Em apenas algumas linhas, é possível criar algumas aplicações bastante poderosas, por isso estou curioso para ver o que se pode arranjar!

Categorias: Articles

0 comentários

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *