WebSockets - Guia rápido
Em termos literais, o aperto de mão pode ser definido como agarrar e apertar a mão direita por duas pessoas, como símbolo de saudação, parabéns, acordo ou despedida. Na ciência da computação, o handshaking é um processo que garante que o servidor esteja em sincronia com seus clientes. O handshaking é o conceito básico do protocolo Web Socket.
O diagrama a seguir mostra o handshake do servidor com vários clientes -
Web Sockets - Definição
Web sockets são definidos como uma comunicação bidirecional entre os servidores e os clientes, o que significa que ambas as partes se comunicam e trocam dados ao mesmo tempo.
Os pontos principais dos Web Sockets são true concurrency e optimization of performance, resultando em aplicativos da web mais responsivos e ricos.
Descrição do protocolo Web Socket
Este protocolo define uma comunicação full duplex desde o início. Os soquetes da Web dão um passo à frente ao trazer funcionalidades ricas de desktop para os navegadores da web. Representa uma evolução há muito esperada na tecnologia cliente / servidor web.
As principais características dos web sockets são as seguintes -
O protocolo Web socket está sendo padronizado, o que significa que a comunicação em tempo real entre servidores web e clientes é possível com a ajuda deste protocolo.
Os soquetes da Web estão se transformando em um padrão de plataforma cruzada para comunicação em tempo real entre um cliente e o servidor.
Este padrão permite novos tipos de aplicativos. As empresas de aplicativos da web em tempo real podem acelerar com a ajuda dessa tecnologia.
A maior vantagem do Web Socket é que ele fornece uma comunicação bidirecional (full duplex) em uma única conexão TCP.
URL
O HTTP tem seu próprio conjunto de esquemas, como http e https. O protocolo de soquete da Web também possui um esquema semelhante definido em seu padrão de URL.
A imagem a seguir mostra o URL do Web Socket em tokens.
Suporte de navegador
A especificação mais recente do protocolo Web Socket é definida como RFC 6455 - um padrão proposto.
RFC 6455 é compatível com vários navegadores como Internet Explorer, Mozilla Firefox, Google Chrome, Safari e Opera.
Antes de mergulhar na necessidade de Web sockets, é necessário dar uma olhada nas técnicas existentes, que são utilizadas para duplex communicationentre o servidor e o cliente. Eles são os seguintes -
- Polling
- Long Polling
- Streaming
- Postback e AJAX
- HTML5
Votação
O polling pode ser definido como um método que realiza solicitações periódicas, independentemente dos dados existentes na transmissão. As solicitações periódicas são enviadas de forma síncrona. O cliente faz uma solicitação periódica em um intervalo de tempo especificado ao servidor. A resposta do servidor inclui dados disponíveis ou alguma mensagem de aviso nele.
Long Polling
As pesquisas longas, como o nome sugere, incluem técnicas semelhantes às das pesquisas. O cliente e o servidor mantêm a conexão ativa até que alguns dados sejam buscados ou ocorra o tempo limite. Se a conexão for perdida por algum motivo, o cliente pode reiniciar e executar a solicitação sequencial.
A sondagem longa nada mais é do que melhoria de desempenho em relação ao processo de sondagem, mas solicitações constantes podem retardar o processo.
Transmissão
É considerada a melhor opção para transmissão de dados em tempo real. O servidor mantém a conexão aberta e ativa com o cliente até e a menos que os dados necessários estejam sendo buscados. Nesse caso, a conexão é considerada aberta indefinidamente. O streaming inclui cabeçalhos HTTP que aumentam o tamanho do arquivo, aumentando o atraso. Isso pode ser considerado uma grande desvantagem.
AJAX
AJAX é baseado em Javascript XmlHttpRequestObjeto. É uma forma abreviada de Javascript assíncrono e XML.XmlHttpRequestO objeto permite a execução do Javascript sem recarregar a página da web completa. AJAX envia e recebe apenas uma parte da página da web.
O snippet de código da chamada AJAX com XmlHttpRequest O objeto é o seguinte -
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
As principais desvantagens de AJAX em comparação com Web Sockets são -
- Eles enviam cabeçalhos HTTP, o que aumenta o tamanho total.
- A comunicação é half-duplex.
- O servidor web consome mais recursos.
HTML5
HTML5 é uma estrutura robusta para desenvolver e projetar aplicativos da web. Os principais pilares incluemMark-up, CSS3 e Javascript APIs juntos.
O diagrama a seguir mostra os componentes HTML5 -
O trecho de código fornecido abaixo descreve a declaração de HTML5 e seu doctype.
<!DOCTYPE html>
Por que precisamos de Web Sockets?
A Internet foi concebida para ser uma coleção de páginas em linguagem de marcação de hipertexto (HTML) que se ligam umas às outras para formar uma rede conceitual de informações. Com o passar do tempo, os recursos estáticos aumentaram em número e itens mais ricos, como imagens, e passaram a fazer parte da web fabric.
Tecnologias avançadas de servidor que permitem páginas de servidor dinâmicas - páginas cujo conteúdo foi gerado com base em uma consulta.
Logo, a necessidade de ter páginas da web mais dinâmicas levou à disponibilidade de Dynamic Hypertext Mark-up Language (DHTML). Tudo graças ao JavaScript. Nos anos seguintes, vimoscross frame communication em uma tentativa de evitar recarregamentos de página seguidos por HTTP Polling dentro de quadros.
No entanto, nenhuma dessas soluções ofereceu uma solução verdadeiramente padronizada para vários navegadores para comunicação bidirecional em tempo real entre um servidor e um cliente.
Isso deu origem à necessidade do protocolo Web Sockets. Isso deu origem à comunicação full-duplex trazendo funcionalidades ricas em desktop para todos os navegadores da web.
O Web Socket representa uma grande atualização na história das comunicações na web. Antes de sua existência, toda comunicação entre os clientes da web e os servidores dependia apenas de HTTP.
Web Socket ajuda no fluxo dinâmico das conexões full duplex persistentes. Full duplex refere-se à comunicação de ambas as extremidades com velocidade rápida considerável.
É denominado como um divisor de águas por causa de sua eficiência em superar todas as desvantagens dos protocolos existentes.
Web Socket para desenvolvedores e arquitetos
Importância do Web Socket para desenvolvedores e arquitetos -
O Web Socket é um protocolo independente baseado em TCP, mas foi projetado para oferecer suporte a qualquer outro protocolo que tradicionalmente seria executado apenas em uma conexão TCP pura.
O Web Socket é uma camada de transporte sobre a qual qualquer outro protocolo pode ser executado. A API Web Socket suporta a capacidade de definir subprotocolos: bibliotecas de protocolo que podem interpretar protocolos específicos.
Exemplos de tais protocolos incluem XMPP, STOMP e AMQP. Os desenvolvedores não precisam mais pensar em termos do paradigma de solicitação-resposta HTTP.
O único requisito no lado do navegador é executar uma biblioteca JavaScript que possa interpretar o handshake do Web Socket, estabelecer e manter uma conexão do Web Socket.
No lado do servidor, o padrão da indústria é usar bibliotecas de protocolo existentes que rodam sobre TCP e alavancar um Web Socket Gateway.
O diagrama a seguir descreve as funcionalidades do Web Sockets -
As conexões do Web Socket são iniciadas via HTTP; Os servidores HTTP normalmente interpretam os handshakes do Web Socket como uma solicitação de atualização.
Os Web Sockets podem ser um complemento complementar para um ambiente HTTP existente e podem fornecer a infraestrutura necessária para adicionar funcionalidade da web. Ele se baseia em protocolos full duplex mais avançados que permitem que os dados fluam em ambas as direções entre o cliente e o servidor.
Funções de Web Sockets
Os Web Sockets fornecem uma conexão entre o servidor da web e um cliente de forma que ambas as partes possam começar a enviar os dados.
As etapas para estabelecer a conexão do Web Socket são as seguintes -
O cliente estabelece uma conexão por meio de um processo conhecido como Web Socket handshake.
O processo começa com o cliente enviando uma solicitação HTTP regular ao servidor.
Um cabeçalho de atualização é solicitado. Nessa solicitação, ele informa ao servidor que a solicitação é para conexão do Web Socket.
URLs de Web Socket usam o wsesquema. Eles também são usados para conexões seguras de Web Socket, que são equivalentes a HTTPs.
Um exemplo simples de cabeçalhos de solicitação inicial é o seguinte -
GET ws://websocket.example.com/ HTTP/1.1
Origin: http://example.com
Connection: Upgrade
Host: websocket.example.com
Upgrade: websocket
Os Web Sockets ocupam um papel fundamental não apenas na web, mas também na indústria móvel. A importância dos Web Sockets é apresentada a seguir.
Os Web Sockets, como o nome indica, estão relacionados à web. A Web consiste em várias técnicas para alguns navegadores; é uma ampla plataforma de comunicação para um grande número de dispositivos, incluindo computadores desktop, laptops, tablets e smartphones.
O aplicativo HTML5 que utiliza Web Sockets funcionará em qualquer navegador habilitado para HTML5.
O soquete da Web é compatível com os sistemas operacionais convencionais. Todos os principais participantes da indústria móvel fornecem APIs de Web Socket em seus próprios aplicativos nativos.
Os soquetes da Web são considerados uma comunicação full duplex. A abordagem dos Web Sockets funciona bem para certas categorias de aplicativos da web, como salas de chat, onde as atualizações do cliente e do servidor são compartilhadas simultaneamente.
Web Sockets, uma parte da especificação HTML5, permite a comunicação full duplex entre as páginas da web e um host remoto. O protocolo é projetado para alcançar os seguintes benefícios, que podem ser considerados os pontos principais -
Reduce unnecessary network traffic and latency usando full duplex por meio de uma única conexão (em vez de duas).
Streaming through proxies and firewalls, com o suporte de comunicação upstream e downstream simultaneamente.
É necessário inicializar a conexão do cliente ao servidor para a comunicação entre eles. Para inicializar a conexão, é necessária a criação de um objeto Javascript com a URL com o servidor remoto ou local.
var socket = new WebSocket(“ ws://echo.websocket.org ”);
O URL mencionado acima é um endereço público que pode ser usado para testes e experimentos. O servidor websocket.org está sempre ativo e quando recebe a mensagem e a envia de volta para o cliente.
Esta é a etapa mais importante para garantir que o aplicativo funcione corretamente.
Web Sockets - Eventos
Existem quatro principais Web Socket API events -
- Open
- Message
- Close
- Error
Cada um dos eventos são tratados implementando funções como onopen, onmessage, onclose e onerrorfunções respectivamente. Também pode ser implementado com a ajuda do método addEventListener.
A breve visão geral dos eventos e funções são descritos a seguir -
Abrir
Assim que a conexão for estabelecida entre o cliente e o servidor, o evento open é disparado a partir da instância do Web Socket. É chamado de handshake inicial entre cliente e servidor. O evento, que é gerado assim que a conexão é estabelecida, é chamadoonopen.
mensagem
O evento de mensagem ocorre geralmente quando o servidor envia alguns dados. As mensagens enviadas pelo servidor para o cliente podem incluir mensagens de texto simples, dados binários ou imagens. Sempre que os dados são enviados, oonmessage função é disparada.
Fechar
O evento Close marca o fim da comunicação entre o servidor e o cliente. Fechar a conexão é possível com a ajuda deoncloseevento. Após marcar o fim da comunicação com a ajuda deoncloseevento, nenhuma mensagem pode ser transferida entre o servidor e o cliente. O fechamento do evento também pode acontecer devido à falta de conectividade.
Erro
Marcas de erro para algum engano, que acontece durante a comunicação. É marcado com a ajuda deonerror evento. Onerroré sempre seguido pelo encerramento da conexão. A descrição detalhada de cada evento é discutida em capítulos posteriores.
Web Sockets - Ações
Os eventos geralmente são acionados quando algo acontece. Por outro lado, as ações são realizadas quando um usuário deseja que algo aconteça. As ações são feitas por chamadas explícitas usando funções dos usuários.
O protocolo Web Socket suporta duas ações principais, a saber -
- enviar( )
- Fechar( )
enviar ( )
Esta ação é geralmente preferida para alguma comunicação com o servidor, o que inclui o envio de mensagens, o que inclui arquivos de texto, dados binários ou imagens.
Uma mensagem de bate-papo, que é enviada com a ajuda da ação send (), é a seguinte -
// get text view and button for submitting the message
var textsend = document.getElementById(“text-view”);
var submitMsg = document.getElementById(“tsend-button”);
//Handling the click event
submitMsg.onclick = function ( ) {
// Send the data
socket.send( textsend.value);
}
Note - O envio das mensagens só é possível se a conexão estiver aberta.
Fechar ( )
Este método significa aperto de mão de adeus. Ele encerra a conexão completamente e nenhum dado pode ser transferido até que a conexão seja restabelecida.
var textsend = document.getElementById(“text-view”);
var buttonStop = document.getElementById(“stop-button”);
//Handling the click event
buttonStop.onclick = function ( ) {
// Close the connection if open
if (socket.readyState === WebSocket.OPEN){
socket.close( );
}
}
Também é possível fechar a conexão deliberadamente com a ajuda do seguinte trecho de código -
socket.close(1000,”Deliberate Connection”);
Depois que uma conexão é estabelecida entre o cliente e o servidor, o evento open é disparado da instância do Web Socket. É chamado de handshake inicial entre cliente e servidor.
O evento, que é gerado assim que a conexão é estabelecida, é chamado de onopen. Criar conexões Web Socket é realmente simples. Tudo que você precisa fazer é ligar para oWebSocket constructor e passe a URL do seu servidor.
O código a seguir é usado para criar uma conexão Web Socket -
// Create a new WebSocket.
var socket = new WebSocket('ws://echo.websocket.org');
Assim que a conexão for estabelecida, o evento open será disparado em sua instância do Web Socket.
onopen refere-se ao handshake inicial entre o cliente e o servidor que levou ao primeiro negócio e o aplicativo da web está pronto para transmitir os dados.
O seguinte snippet de código descreve a abertura da conexão do protocolo Web Socket -
socket.onopen = function(event) {
console.log(“Connection established”);
// Display user friendly messages for the successful establishment of connection
var.label = document.getElementById(“status”);
label.innerHTML = ”Connection established”;
}
É uma boa prática fornecer feedback adequado aos usuários que aguardam o estabelecimento da conexão do Web Socket. No entanto, é sempre observado que as conexões do Web Socket são comparativamente rápidas.
A demonstração da conexão do Web Socket estabelecida é documentada no URL fornecido - https://www.websocket.org/echo.html
Um instantâneo do estabelecimento da conexão e da resposta ao usuário é mostrado abaixo -
O estabelecimento de um estado aberto permite a comunicação full duplex e a transferência de mensagens até que a conexão seja encerrada.
Exemplo
Construindo o arquivo cliente-HTML5.
<!DOCTYPE html>
<html>
<meta charset = "utf-8" />
<title>WebSocket Test</title>
<script language = "javascript" type = "text/javascript">
var wsUri = "ws://echo.websocket.org/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
}
function onOpen(evt) {
writeToScreen("CONNECTED");
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id = "output"></div>
</html>
O resultado será o seguinte -
O arquivo HTML5 e JavaScript acima mostra a implementação de dois eventos do Web Socket, a saber -
onLoad que ajuda na criação do objeto JavaScript e inicialização da conexão.
onOpen estabelece conexão com o servidor e também envia o status.
Uma vez que uma conexão foi estabelecida entre o cliente e o servidor, um openevento é disparado da instância do Web Socket. Erros são gerados por erros que ocorrem durante a comunicação. É marcado com a ajuda deonerror evento. Onerror é sempre seguido pelo encerramento da conexão.
o onerrorevento é disparado quando algo de errado ocorre entre as comunicações. O eventoonerror é seguido por um encerramento de conexão, que é um close evento.
Uma boa prática é sempre informar o usuário sobre o erro inesperado e tentar reconectá-lo.
socket.onclose = function(event) {
console.log("Error occurred.");
// Inform the user about the error.
var label = document.getElementById("status-label");
label.innerHTML = "Error: " + event;
}
Quando se trata de tratamento de erros, você deve considerar os parâmetros internos e externos.
Os parâmetros internos incluem erros que podem ser gerados por causa de bugs em seu código ou comportamento inesperado do usuário.
Erros externos não têm nada a ver com o aplicativo; em vez disso, eles estão relacionados a parâmetros que não podem ser controlados. O mais importante é a conectividade da rede.
Qualquer aplicativo da web bidirecional interativo requer, bem, uma conexão ativa com a Internet.
Verificando a disponibilidade da rede
Imagine que seus usuários estão curtindo seu aplicativo da web quando, de repente, a conexão de rede deixa de responder no meio de sua tarefa. Em aplicativos nativos modernos de desktop e móveis, é uma tarefa comum verificar a disponibilidade da rede.
A maneira mais comum de fazer isso é simplesmente fazer uma solicitação HTTP para um site que deveria estar ativo (por exemplo, http://www.google.com). Se a solicitação for bem-sucedida, o desktop ou dispositivo móvel saberá que há conectividade ativa. Da mesma forma, HTML temXMLHttpRequest para determinar a disponibilidade da rede.
O HTML5, entretanto, tornou tudo ainda mais fácil e introduziu uma maneira de verificar se o navegador pode aceitar respostas da web. Isso é feito por meio do objeto navegador -
if (navigator.onLine) {
alert("You are Online");
}else {
alert("You are Offline");
}
O modo offline significa que o dispositivo não está conectado ou o usuário selecionou o modo offline na barra de ferramentas do navegador.
Veja como informar ao usuário que a rede não está disponível e tentar se reconectar quando ocorrer um evento de fechamento do WebSocket -
socket.onclose = function (event) {
// Connection closed.
// Firstly, check the reason.
if (event.code != 1000) {
// Error code 1000 means that the connection was closed normally.
// Try to reconnect.
if (!navigator.onLine) {
alert("You are offline. Please connect to the Internet and try again.");
}
}
}
Demo para receber mensagens de erro
O programa a seguir explica como mostrar mensagens de erro usando Web Sockets -
<!DOCTYPE html>
<html>
<meta charset = "utf-8" />
<title>WebSocket Test</title>
<script language = "javascript" type = "text/javascript">
var wsUri = "ws://echo.websocket.org/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
}
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
function onError(evt) {
writeToScreen('<span style = "color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message); websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message; output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id = "output"></div>
</html>
O resultado é o seguinte -
o Messageevento ocorre geralmente quando o servidor envia alguns dados. As mensagens enviadas pelo servidor para o cliente podem incluir mensagens de texto simples, dados binários ou imagens. Sempre que os dados são enviados, oonmessage função é disparada.
Este evento atua como um ouvido do cliente para o servidor. Sempre que o servidor envia dados, oonmessage evento é disparado.
O fragmento de código a seguir descreve a abertura da conexão do protocolo Web Socket.
connection.onmessage = function(e){
var server_message = e.data;
console.log(server_message);
}
Também é necessário levar em consideração quais tipos de dados podem ser transferidos com a ajuda de Web Sockets. O protocolo de soquete da Web oferece suporte a dados binários e de texto. Em termos de Javascript,text refere-se a uma string, enquanto os dados binários são representados como ArrayBuffer.
Os soquetes da Web suportam apenas um formato binário por vez. A declaração de dados binários é feita explicitamente da seguinte forma -
socket.binaryType = ”arrayBuffer”;
socket.binaryType = ”blob”;
Cordas
Strings são consideradas úteis, lidando com formatos legíveis por humanos, como XML e JSON. Sempre queonmessage evento é gerado, o cliente precisa verificar o tipo de dados e agir de acordo.
O snippet de código para determinar o tipo de dados como String é mencionado abaixo -
socket.onmessage = function(event){
if(typeOf event.data === String ) {
console.log(“Received data string”);
}
}
JSON (JavaScript Object Notation)
É um formato leve para a transferência de dados legíveis por humanos entre os computadores. A estrutura do JSON consiste em pares de valores-chave.
Exemplo
{
name: “James Devilson”,
message: “Hello World!”
}
O código a seguir mostra como lidar com um objeto JSON e extrair suas propriedades -
socket.onmessage = function(event) {
if(typeOf event.data === String ){
//create a JSON object
var jsonObject = JSON.parse(event.data);
var username = jsonObject.name;
var message = jsonObject.message;
console.log(“Received data string”);
}
}
XML
A análise em XML não é difícil, embora as técnicas difiram de navegador para navegador. O melhor método é analisar usando uma biblioteca de terceiros como jQuery.
Em XML e JSON, o servidor responde como uma string, que está sendo analisada na extremidade do cliente.
ArrayBuffer
Consiste em dados binários estruturados. Os bits incluídos são fornecidos em uma ordem para que a posição possa ser facilmente rastreada. ArrayBuffers são úteis para armazenar os arquivos de imagem.
Receber dados usando ArrayBuffers é bastante simples. O operadorinstanceOf é usado em vez do operador igual.
O código a seguir mostra como lidar e receber um objeto ArrayBuffer -
socket.onmessage = function(event) {
if(event.data instanceof ArrayBuffer ){
var buffer = event.data;
console.log(“Received arraybuffer”);
}
}
Aplicativo de demonstração
O código de programa a seguir mostra como enviar e receber mensagens usando Web Sockets.
<!DOCTYPE html>
<html>
<meta charset = "utf-8" />
<title>WebSocket Test</title>
<script language = "javascript" type = "text/javascript">
var wsUri = "ws://echo.websocket.org/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
}
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onMessage(evt) {
writeToScreen('<span style = "color: blue;">RESPONSE: ' +
evt.data+'</span>'); websocket.close();
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message); websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message; output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id = "output"></div>
</html>
A saída é mostrada abaixo.
Closeevento marca o fim de uma comunicação entre o servidor e o cliente. Fechar uma conexão é possível com a ajuda deoncloseevento. Após marcar o fim da comunicação com a ajuda deoncloseevento, nenhuma mensagem pode ser transferida entre o servidor e o cliente. O fechamento do evento também pode ocorrer devido à falta de conectividade.
o close() método significa goodbye handshake. Ele encerra a conexão e nenhum dado pode ser trocado, a menos que a conexão seja aberta novamente.
Semelhante ao exemplo anterior, chamamos o close() método quando o usuário clica no segundo botão.
var textView = document.getElementById("text-view");
var buttonStop = document.getElementById("stop-button");
buttonStop.onclick = function() {
// Close the connection, if open.
if (socket.readyState === WebSocket.OPEN) {
socket.close();
}
}
Também é possível passar os parâmetros de código e de razão que mencionamos anteriormente, conforme mostrado abaixo.
socket.close(1000, "Deliberate disconnection");
O código a seguir oferece uma visão geral completa de como fechar ou desconectar uma conexão Web Socket -
<!DOCTYPE html>
<html>
<meta charset = "utf-8" />
<title>WebSocket Test</title>
<script language = "javascript" type = "text/javascript">
var wsUri = "ws://echo.websocket.org/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
}
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
function onMessage(evt) {
writeToScreen('<span style = "color: blue;">RESPONSE: ' +
evt.data+'</span>'); websocket.close();
}
function onError(evt) {
writeToScreen('<span style = "color: red;">ERROR:</span> '
+ evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message); websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id = "output"></div>
</html>
O resultado é o seguinte -
Um servidor Web Socket é um programa simples, que tem a capacidade de manipular eventos e ações do Web Socket. Geralmente, ele expõe métodos semelhantes para a API do cliente Web Socket e a maioria das linguagens de programação fornece uma implementação. O diagrama a seguir ilustra o processo de comunicação entre um servidor Web Socket e um cliente Web Socket, enfatizando os eventos e ações acionados.
O diagrama a seguir mostra um servidor Web Socket e o acionamento de eventos de cliente -
Conectando-se ao servidor web
O servidor Web Socket funciona de maneira semelhante aos clientes Web Socket. Ele responde a eventos e executa ações quando necessário. Independentemente da linguagem de programação usada, cada servidor Web Socket executa algumas ações específicas.
Ele é inicializado com um endereço Web Socket. Lida comOnOpen, OnClose, e OnMessage eventos e também envia mensagens aos clientes.
Criação de uma instância de servidor Web Socket
Cada servidor Web Socket precisa de um host e uma porta válidos. Um exemplo de criação de uma instância do Web Socket no servidor é o seguinte -
var server = new WebSocketServer("ws://localhost:8181");
Qualquer URL válido pode ser usado com a especificação de uma porta, que não foi usada anteriormente. É muito útil manter um registro dos clientes conectados, pois fornece detalhes com dados diferentes ou envia mensagens diferentes para cada um.
Fleck representa as conexões de entrada (clientes) com o IwebSocketConnectioninterface. Sempre que alguém se conecta ou desconecta de nosso serviço, uma lista vazia pode ser criada ou atualizada.
var clients = new List<IWebSocketConnection>();
Depois disso, podemos chamar o Startmétodo e aguarde os clientes se conectarem. Depois de iniciar, o servidor é capaz de aceitar conexões de entrada. Em Fleck, o método Start precisa de um parâmetro, que indica o soquete que gerou os eventos -
server.Start(socket) =>
{
});
Evento OnOpen
o OnOpenevento determina que um novo cliente solicitou acesso e executa um handshake inicial. O cliente deve ser adicionado à lista e provavelmente as informações relacionadas a ele devem ser armazenadas, como o endereço IP. Fleck nos fornece essas informações, bem como um identificador único para a conexão.
server.Start(socket) ⇒ {
socket.OnOpen = () ⇒ {
// Add the incoming connection to our list.
clients.Add(socket);
}
// Handle the other events here...
});
Evento OnClose
o OnCloseevento é gerado sempre que um cliente é desconectado. O Cliente é retirado da lista e informa o resto dos clientes sobre a desconexão.
socket.OnClose = () ⇒ {
// Remove the disconnected client from the list.
clients.Remove(socket);
};
Evento OnMessage
o OnMessageevento é gerado quando um cliente envia dados ao servidor. Dentro desse manipulador de eventos, a mensagem de entrada pode ser transmitida aos clientes ou provavelmente selecionar apenas alguns deles.
O processo é simples. Observe que este manipulador recebe uma string chamadamessage como parâmetro -
socket.OnMessage = () ⇒ {
// Display the message on the console.
Console.WriteLine(message);
};
Método Send ()
o Send()método simplesmente transmite a mensagem desejada para o cliente especificado. Usando Send (), dados de texto ou binários podem ser armazenados nos clientes.
O trabalho de OnMessage evento é o seguinte -
socket.OnMessage = () ⇒ {
foreach (var client in clients) {
// Send the message to everyone!
// Also, send the client connection's unique identifier in order
// to recognize who is who.
client.Send(client.ConnectionInfo.Id + " says: " + message);
}
};
API - Definição
API, uma abreviatura de Application Program Interface, é um conjunto de rotinas, protocolos e ferramentas para construir aplicativos de software.
Alguns recursos importantes são -
A API especifica como os componentes de software devem interagir e as APIs devem ser usadas ao programar componentes da interface gráfica do usuário (GUI).
Uma boa API torna mais fácil desenvolver um programa, fornecendo todos os blocos de construção.
REST, que normalmente é executado em HTTP, é frequentemente usado em aplicativos móveis, sites sociais, ferramentas de mashup e processos de negócios automatizados.
O estilo REST enfatiza que as interações entre os clientes e serviços são aprimoradas por ter um número limitado de operações (verbos).
A flexibilidade é fornecida pela atribuição de recursos; seus próprios identificadores de recursos universais (URIs) exclusivos.
REST evita ambigüidade porque cada verbo tem um significado específico (GET, POST, PUT e DELETE)
Vantagens do Web Socket
O Web Socket resolve alguns problemas com REST ou HTTP em geral -
Bidirecional
HTTP é um protocolo unidirecional em que o cliente sempre inicia uma solicitação. O servidor processa e retorna uma resposta e, em seguida, o cliente a consome. Web Socket é um protocolo bidirecional em que não há padrões de mensagem predefinidos, como solicitação / resposta. Tanto o cliente quanto o servidor podem enviar uma mensagem para a outra parte.
Full Duplex
O HTTP permite que a mensagem de solicitação vá do cliente para o servidor e, em seguida, o servidor envia uma mensagem de resposta ao cliente. Em um determinado momento, o cliente está conversando com o servidor ou o servidor está conversando com o cliente. O Web Socket permite que o cliente e o servidor conversem independentemente um do outro.
Conexão TCP Única
Normalmente, uma nova conexão TCP é iniciada para uma solicitação HTTP e encerrada após o recebimento da resposta. Uma nova conexão TCP precisa ser estabelecida para outra solicitação / resposta HTTP. Para o Web Socket, a conexão HTTP é atualizada usando o mecanismo de atualização HTTP padrão e o cliente e o servidor se comunicam por meio dessa mesma conexão TCP durante o ciclo de vida da conexão Web Socket.
O gráfico abaixo mostra o tempo (em milissegundos) gasto para processar N mensagens para um tamanho de carga útil constante.
Aqui estão os dados brutos que alimentam este gráfico -
O gráfico e a tabela fornecidos acima mostram que a sobrecarga REST aumenta com o número de mensagens. Isso ocorre porque muitas conexões TCP precisam ser iniciadas e encerradas e muitos cabeçalhos HTTP precisam ser enviados e recebidos.
A última coluna mostra particularmente o fator de multiplicação para a quantidade de tempo para atender uma solicitação REST.
O segundo gráfico mostra o tempo gasto para processar um número fixo de mensagens variando o tamanho da carga útil.
Aqui estão os dados brutos que alimentam este gráfico -
Este gráfico mostra que o custo incremental de processamento da solicitação / resposta para um terminal REST é mínimo e a maior parte do tempo é gasto no início / término da conexão e no respeito à semântica HTTP.
Conclusão
Web Socket é um protocolo de baixo nível. Tudo, incluindo um padrão de design de solicitação / resposta simples, como criar / atualizar / excluir a necessidade de recursos, códigos de status etc. Todos esses são bem definidos para HTTP.
O Web Socket é um protocolo com estado, enquanto o HTTP é um protocolo sem estado. As conexões Web Socket podem ser dimensionadas verticalmente em um único servidor, enquanto o HTTP pode ser dimensionado horizontalmente. Existem algumas soluções proprietárias para dimensionamento horizontal do Web Socket, mas elas não são baseadas em padrões. O HTTP vem com muitos outros recursos, como cache, roteamento e multiplexação. Todos eles precisam ser definidos no topo do Web Socket.
O código de programa a seguir descreve o funcionamento de um aplicativo de bate-papo usando o protocolo JavaScript e Web Socket.
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = utf-8>
<title>HTML5 Chat</title>
<body>
<section id = "wrapper">
<header>
<h1>HTML5 Chat</h1>
</header>
<style>
#chat { width: 97%; }
.message { font-weight: bold; }
.message:before { content: ' '; color: #bbb; font-size: 14px; }
#log {
overflow: auto;
max-height: 300px;
list-style: none;
padding: 0;
}
#log li {
border-top: 1px solid #ccc;
margin: 0;
padding: 10px 0;
}
body {
font: normal 16px/20px "Helvetica Neue", Helvetica, sans-serif;
background: rgb(237, 237, 236);
margin: 0;
margin-top: 40px;
padding: 0;
}
section, header {
display: block;
}
#wrapper {
width: 600px;
margin: 0 auto;
background: #fff;
border-radius: 10px;
border-top: 1px solid #fff;
padding-bottom: 16px;
}
h1 {
padding-top: 10px;
}
h2 {
font-size: 100%;
font-style: italic;
}
header, article > * {
margin: 20px;
}
#status {
padding: 5px;
color: #fff;
background: #ccc;
}
#status.fail {
background: #c00;
}
#status.success {
background: #0c0;
}
#status.offline {
background: #c00;
}
#status.online {
background: #0c0;
}
#html5badge {
margin-left: -30px;
border: 0;
}
#html5badge img {
border: 0;
}
</style>
<article>
<form onsubmit = "addMessage(); return false;">
<input type = "text" id = "chat" placeholder = "type and press
enter to chat" />
</form>
<p id = "status">Not connected</p>
<p>Users connected: <span id = "connected">0
</span></p>
<ul id = "log"></ul>
</article>
<script>
connected = document.getElementById("connected");
log = document.getElementById("log");
chat = document.getElementById("chat");
form = chat.form;
state = document.getElementById("status");
if (window.WebSocket === undefined) {
state.innerHTML = "sockets not supported";
state.className = "fail";
}else {
if (typeof String.prototype.startsWith != "function") {
String.prototype.startsWith = function (str) {
return this.indexOf(str) == 0;
};
}
window.addEventListener("load", onLoad, false);
}
function onLoad() {
var wsUri = "ws://127.0.0.1:7777";
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt) {
state.className = "success";
state.innerHTML = "Connected to server";
}
function onClose(evt) {
state.className = "fail";
state.innerHTML = "Not connected";
connected.innerHTML = "0";
}
function onMessage(evt) {
// There are two types of messages:
// 1. a chat participant message itself
// 2. a message with a number of connected chat participants
var message = evt.data;
if (message.startsWith("log:")) {
message = message.slice("log:".length);
log.innerHTML = '<li class = "message">' +
message + "</li>" + log.innerHTML;
}else if (message.startsWith("connected:")) {
message = message.slice("connected:".length);
connected.innerHTML = message;
}
}
function onError(evt) {
state.className = "fail";
state.innerHTML = "Communication error";
}
function addMessage() {
var message = chat.value;
chat.value = "";
websocket.send(message);
}
</script>
</section>
</body>
</head>
</html>
Os principais recursos e a saída do aplicativo de bate-papo são discutidos abaixo -
Para testar, abra as duas janelas com suporte para Web Socket, digite uma mensagem acima e pressione Enter. Isso habilitaria o recurso de aplicativo de bate-papo.
Se a conexão não for estabelecida, a saída estará disponível conforme mostrado abaixo.
A saída de uma comunicação de bate-papo bem-sucedida é mostrada abaixo.
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 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 de entrada recebidas ou 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);
};
Comunicando-se 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 de origem cruzada é 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 servidor 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.
O protocolo deve ser projetado por razões de segurança. WebSocket é um protocolo totalmente novo e nem todos os navegadores da web o implementam corretamente. Por exemplo, alguns deles ainda permitem a combinação de HTTP e WS, embora a especificação implique o contrário. Neste capítulo, discutiremos alguns ataques de segurança comuns dos quais o usuário deve estar ciente.
Negação de serviço
Ataques de negação de serviço (DoS) tentam tornar uma máquina ou recurso de rede indisponível para os usuários que o solicitam. Suponha que alguém faça um número infinito de solicitações a um servidor da web com nenhum ou pequenos intervalos de tempo. O servidor não consegue lidar com cada conexão e irá parar de responder ou continuará respondendo muito lentamente. Isso pode ser denominado como ataque de negação de serviço.
A negação de serviço é muito frustrante para os usuários finais, que não conseguiam nem mesmo carregar uma página da web.
O ataque DoS pode até mesmo se aplicar a comunicações ponto a ponto, forçando os clientes de uma rede P2P a se conectarem simultaneamente ao servidor web da vítima.
Homem no meio
Vamos entender isso com a ajuda de um exemplo.
Suponha que uma pessoa A está conversando com o amigo dele Bpor meio de um cliente de IM. Uma terceira pessoa deseja ver as mensagens que você troca. Então, ele faz conexões independentes com ambas as pessoas. Ele também envia mensagens para pessoasA e seu amigo B, como um intermediário invisível para sua comunicação. Isso é conhecido como ataque man-in-the-middle.
O tipo de ataque man-in-the-middle é mais fácil para conexões não criptografadas, pois o invasor pode ler os pacotes diretamente. Quando a conexão é criptografada, as informações precisam ser descriptografadas pelo invasor, o que pode ser muito difícil.
Do ponto de vista técnico, o invasor intercepta uma troca de mensagem de chave pública e a envia enquanto substitui a chave solicitada pela sua. Obviamente, uma estratégia sólida para dificultar o trabalho do invasor é usar SSH com WebSockets.
Principalmente ao trocar dados críticos, prefira a conexão segura WSS em vez do WS não criptografado.
XSS
Cross-site scripting (XSS) é uma vulnerabilidade que permite que invasores injetem scripts do lado do cliente em páginas da web ou aplicativos. Um invasor pode enviar código HTML ou Javascript usando seus hubs de aplicativo e permitir que esse código seja executado nas máquinas dos clientes.
Mecanismos de defesa nativa WebSocket
Por padrão, o protocolo WebSocket é projetado para ser seguro. No mundo real, o usuário pode encontrar vários problemas que podem ocorrer devido à implementação deficiente do navegador. Conforme o tempo passa, os fornecedores de navegadores corrigem todos os problemas imediatamente.
Uma camada extra de segurança é adicionada quando uma conexão WebSocket segura sobre SSH (ou TLS) é usada.
No mundo WebSocket, a principal preocupação é com o desempenho de uma conexão segura. Embora ainda haja uma camada TLS extra na parte superior, o próprio protocolo contém otimizações para esse tipo de uso, além disso, o WSS funciona de forma mais elegante por meio de proxies.
Máscara de cliente para servidor
Cada mensagem transmitida entre um servidor WebSocket e um cliente WebSocket contém uma chave específica, denominada chave de mascaramento, que permite a qualquer intermediário compatível com WebSocket desmascarar e inspecionar a mensagem. Se o intermediário não for compatível com WebSocket, a mensagem não será afetada. O navegador que implementa o protocolo WebSocket controla o mascaramento.
Security Toolbox
Finalmente, ferramentas úteis podem ser apresentadas para investigar o fluxo de informações entre seus clientes e servidor WebSocket, analisar os dados trocados e identificar possíveis riscos.
Ferramentas de desenvolvedor de navegador
Chrome, Firefox e Opera são ótimos navegadores em termos de suporte ao desenvolvedor. Suas ferramentas integradas nos ajudam a determinar quase todos os aspectos das interações e recursos do lado do cliente. Ele desempenha um grande papel para fins de segurança.
WebSocket, como o nome indica, é algo que usa a web. A web geralmente está entrelaçada com as páginas do navegador porque esse é o principal meio de exibição de dados online. No entanto, programas sem navegador também usam transmissão de dados online.
O lançamento do iPhone (inicialmente) e do iPad (mais tarde) introduziu um novo mundo de interconectividade web sem necessariamente usar um navegador web. Em vez disso, os novos smartphones e tablets utilizaram o poder dos aplicativos nativos para oferecer uma experiência única ao usuário.
Por que o celular é importante?
Atualmente, há um bilhão de smartphones ativos por aí. Ou seja, milhões de clientes potenciais para seus aplicativos. Essas pessoas usam seus telefones celulares para realizar tarefas diárias, navegar na Internet, comunicar-se ou fazer compras.
Os smartphones se tornaram sinônimos de aplicativos. Hoje em dia, existe um aplicativo para qualquer uso, que o usuário possa imaginar. A maioria dos aplicativos se conecta à Internet para recuperar dados, fazer transações, obter notícias e assim por diante.
Seria ótimo usar o conhecimento existente do WebSocket e desenvolver um cliente WebSocket rodando nativamente em um smartphone ou tablet.
Aplicativo móvel nativo versus site móvel
Bem, este é um conflito comum e como sempre, a resposta depende das necessidades do público-alvo. Se um usuário está familiarizado com as tendências de design moderno, criar um site que seja responsivo e compatível com dispositivos móveis agora é uma obrigação. No entanto, o usuário final deve ter certeza de que o conteúdo, que é o que realmente importa, pode ser acessado tanto por meio de um smartphone quanto por um navegador de desktop clássico.
Definitivamente, um aplicativo da web WebSocket será executado em qualquer navegador compatível com HTML5, incluindo navegadores móveis como Safari para iOS e Chrome para celular. Portanto, não há preocupações sobre problemas de compatibilidade com smartphones.
Pré-requisitos
Para desenvolver um aplicativo para smartphone, é necessária a instalação de ferramentas de desenvolvimento e SDKs.
WebSockets pode atuar como um hub universal para a transmissão de mensagens entre clientes móveis e tablets conectados. Podemos implementar um aplicativo iOS nativo, que se comunica com um servidor WebSocket exatamente como o cliente JavaScript HTML5.