WebSockets - Comunicando-se com o servidor
A Web foi amplamente construída em torno do paradigma de solicitação / resposta de HTTP. Um cliente carrega uma página da web e então nada acontece até que o usuário clique na próxima página. Por volta de 2005, o AJAX começou a tornar a web mais dinâmica. Ainda assim, toda a comunicação HTTP é dirigida pelo cliente, o que requer interação com o usuário ou pesquisa periódica para carregar novos dados do servidor.
As tecnologias que permitem ao servidor enviar os dados a um cliente no exato momento em que ele sabe que novos dados estão disponíveis já existem há algum tempo. Eles têm nomes como"Push" ou “Comet”.
Com long polling, o cliente abre uma conexão HTTP com o servidor, que a mantém aberta até o envio da resposta. Sempre que o servidor realmente possui novos dados, ele envia a resposta. A sondagem longa e as outras técnicas funcionam muito bem. No entanto, todos eles compartilham um problema, eles carregam a sobrecarga de HTTP, o que não os torna adequados para aplicativos de baixa latência. Por exemplo, um jogo de tiro multiplayer no navegador ou qualquer outro jogo online com um componente em tempo real.
Trazendo Sockets para a Web
A especificação Web Socket define uma API que estabelece conexões de "soquete" entre um navegador da web e um servidor. Em termos leigos, existe uma conexão persistente entre o cliente e o servidor e ambas as partes podem começar a enviar dados a qualquer momento.
A conexão de soquete da Web pode ser simplesmente aberta usando um construtor -
var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);
wsé o novo esquema de URL para conexões WebSocket. Também háwss, para uma conexão WebSocket segura da mesma maneira https é usado para conexões HTTP seguras.
Anexar alguns manipuladores de eventos imediatamente à conexão permite que você saiba quando a conexão foi aberta, mensagens recebidas ou se ocorreu um erro.
O segundo argumento aceita opcional subprotocols. Pode ser uma string ou uma matriz de strings. Cada string deve representar umsubprotocol nome e servidor aceita apenas um dos aprovados subprotocolsna matriz. Aceitaramsubprotocol pode ser determinado acessando a propriedade de protocolo do objeto WebSocket.
// When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
// Log messages from the server
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
};
Comunicação com o servidor
Assim que tivermos uma conexão com o servidor (quando o evento open for disparado), podemos começar a enviar dados para o servidor usando o método send (sua mensagem) no objeto de conexão. Ele costumava suportar apenas strings, mas na especificação mais recente, agora também pode enviar mensagens binárias. Para enviar dados binários, o objeto Blob ou ArrayBuffer é usado.
// Sending String
connection.send('your message');
// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
binary[i] = img.data[i];
}
connection.send(binary.buffer);
// Sending file as Blob
var file = document.querySelector('input[type = "file"]').files[0];
connection.send(file);
Da mesma forma, o servidor pode nos enviar mensagens a qualquer momento. Sempre que isso acontece, o retorno de chamada onmessage é acionado. O retorno de chamada recebe um objeto de evento e a mensagem real pode ser acessada por meio da data
propriedade.
O WebSocket também pode receber mensagens binárias nas especificações mais recentes. Os quadros binários podem ser recebidos no formato Blob ou ArrayBuffer. Para especificar o formato do binário recebido, defina a propriedade binaryType do objeto WebSocket como 'blob' ou 'arraybuffer'. O formato padrão é 'blob'.
// Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
connection.binaryType = 'arraybuffer';
connection.onmessage = function(e) {
console.log(e.data.byteLength); // ArrayBuffer object if binary
};
Outro recurso recém-adicionado do WebSocket são as extensões. Usando extensões, será possível enviar frames comprimidos, multiplexados, etc.
// Determining accepted extensions
console.log(connection.extensions);
Comunicação de origem cruzada
Por ser um protocolo moderno, a comunicação entre origens é incorporada diretamente ao WebSocket. O WebSocket permite a comunicação entre as partes em qualquer domínio. O servidor decide se colocará seu serviço à disposição de todos os clientes ou apenas daqueles que residem em um conjunto de domínios bem definidos.
Servidores Proxy
Cada nova tecnologia vem com um novo conjunto de problemas. No caso do WebSocket é a compatibilidade com servidores proxy, que medeiam as conexões HTTP na maioria das redes das empresas. O protocolo WebSocket usa o sistema de atualização HTTP (que normalmente é usado para HTTP / SSL) para "atualizar" uma conexão HTTP para uma conexão WebSocket. Alguns servidores proxy não gostam disso e interromperão a conexão. Portanto, mesmo que um determinado cliente use o protocolo WebSocket, pode não ser possível estabelecer uma conexão. Isso torna a próxima seção ainda mais importante :)
O lado do servidor
Usar o WebSocket cria um novo padrão de uso para aplicativos do lado do servidor. Embora as pilhas de servidores tradicionais, como LAMP, sejam projetadas em torno do ciclo de solicitação / resposta HTTP, muitas vezes não lidam bem com um grande número de conexões WebSocket abertas. Manter um grande número de conexões abertas ao mesmo tempo requer uma arquitetura que receba alta simultaneidade a um baixo custo de desempenho.