HTML5 WebSockets: Guia de Comunicação Real | Web Academy
Enquanto o modelo HTTP clássico opera sob o ciclo de solicitação e resposta e os Server-Sent Events (SSE) transmitem dados exclusivamente do servidor para o cliente, o HTML5 WebSockets estabelece o ápice da interatividade na internet: um canal de comunicação totalmente bidirecional e full-duplex sobre uma única conexão TCP persistente. Com WebSockets, tanto o navegador quanto o servidor podem emitir e receber pacotes de dados de forma assíncrona a qualquer instante, com latência na casa dos milissegundos e sobrecarga quase nula de cabeçalhos.
📑 Índice do Conteúdo
1. A Revolução do Full-Duplex: Como o WebSocket Funciona
Para compreender o salto arquitetural proporcionado pelos WebSockets, compare os três modelos de comunicação web:
- HTTP Tradicional (Half-Duplex com Fechamento): Como enviar cartas pelo correio. Você envia uma requisição, o servidor processa, responde e a conexão é encerrada.
- Server-Sent Events (Unidirecional Contínuo): Como ouvir uma estação de rádio. O servidor transmite informações continuamente, mas o cliente não pode responder pelo mesmo canal.
- WebSockets (Full-Duplex Simultâneo): Como uma ligação telefônica moderna. Ambas as partes estão com o canal aberto continuamente e podem falar e ouvir exatamente ao mesmo tempo, sem interrupções.
2. O Handshake de Atualização (HTTP Upgrade)
Uma conexão WebSocket não começa no vácuo; ela nasce a partir de uma requisição HTTP/1.1 ou HTTP/2 comum que solicita a troca de protocolo (handshake):
<!-- 1. O Navegador envia o pedido de Upgrade -->
GET /chat HTTP/1.1
Host: api.seusite.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
<!-- 2. O Servidor aceita e comuta o protocolo -->
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Após o status 101 Switching Protocols, a conexão deixa de seguir o formato HTTP. A partir desse milissegundo, trafegam-se frames binários compactos de apenas 2 a 10 bytes de cabeçalho (contra milhares de bytes repetitivos de cookies e headers do HTTP comum!).
🔒 Protocolo Seguro Obrigatório: Prefira Sempre WSS://
Assim como usamos HTTPS para páginas seguras, conexões WebSocket devem utilizar o protocolo wss:// (WebSocket Secure com criptografia TLS) em vez de ws:// não encriptado.
Além de proteger os dados contra interceptações (ataques Man-in-the-Middle), o tráfego wss:// atravessa portas seguras (443), impedindo que proxies e firewalls corporativos descartem os pacotes por engano.
3. A API WebSocket no Navegador
No front-end, a instânciação e a gerência do ciclo de vida da conexão são controladas pela classe nativa WebSocket:
| Propriedade / Método | Tipo | Finalidade |
|---|---|---|
new WebSocket(url) |
Construtor | Inicia o handshake e abre o socket na URL indicada (wss://...). |
socket.readyState |
Propriedade (0 a 3) | Indica o estado: 0 (CONNECTING), 1 (OPEN), 2 (CLOSING), 3 (CLOSED). |
socket.onopen |
Evento | Disparado quando o handshake é finalizado e o socket está pronto para trafegar dados. |
socket.onmessage |
Evento | Disparado sempre que uma nova mensagem (texto UTF-8 ou binário) chega do servidor. |
socket.send(dados) |
Método | Transmite uma string de texto, JSON serializado ou dados binários (Blob/ArrayBuffer). |
socket.close(codigo, motivo) |
Método | Fecha voluntariamente a conexão de forma limpa. |
4. Código Prático Completo: Chat Interativo em Tempo Real
Abaixo implementamos uma interface de bate-papo com envio via teclado ou botão, balões diferenciados para mensagens próprias e de terceiros, e feedback visual do estado de conexão:
<div class="wzw-chat-box">
<div class="chat-header">
<h3>💬 Sala de Bate-Papo (WebSocket)</h3>
<span id="chatStatus" class="status-offline">Desconectado</span>
</div>
<!-- Painel onde as mensagens aparecem em cascata -->
<div id="chatMessages" class="chat-messages"></div>
<!-- Formulário de Envio -->
<form id="chatForm" class="chat-input-area">
<input
type="text"
id="msgInput"
placeholder="Digite sua mensagem e pressione Enter..."
autocomplete="off"
required>
<button type="submit" id="btnEnviar" class="btn-send">Enviar</button>
</form>
</div>
.wzw-chat-box {
max-width: 580px;
background-color: #0f172a;
border: 1px solid #1e293b;
border-radius: 8px;
overflow: hidden;
color: #f8fafc;
}
.chat-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 20px;
background-color: #1e293b;
border-bottom: 1px solid #334155;
}
.status-online { color: #10b981; font-weight: bold; font-size: 0.85rem; }
.status-offline { color: #ef4444; font-weight: bold; font-size: 0.85rem; }
.chat-messages {
height: 320px;
padding: 16px;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 10px;
background-color: #0b1120;
}
/* Balões de Conversa */
.msg-bubble {
max-width: 75%;
padding: 10px 14px;
border-radius: 8px;
font-size: 0.95rem;
line-height: 1.4;
}
.msg-me {
align-self: flex-end;
background-color: #2563eb;
color: #ffffff;
border-bottom-right-radius: 2px;
}
.msg-other {
align-self: flex-start;
background-color: #1e293b;
color: #f1f5f9;
border: 1px solid #334155;
border-bottom-left-radius: 2px;
}
.chat-input-area {
display: flex;
padding: 12px;
background-color: #1e293b;
gap: 8px;
}
.chat-input-area input {
flex: 1;
padding: 10px 14px;
background-color: #0f172a;
border: 1px solid #334155;
border-radius: 6px;
color: #fff;
outline: none;
}
.chat-input-area input:focus {
border-color: #38bdf8;
}
.btn-send {
padding: 10px 18px;
background-color: #10b981;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
}
// Código JavaScript do Chat
const statusEl = document.getElementById('chatStatus');
const messagesEl = document.getElementById('chatMessages');
const formEl = document.getElementById('chatForm');
const inputEl = document.getElementById('msgInput');
// 1. Conexão ao servidor de Echo público para demonstração imediata
// (Em produção, aponte para: 'wss://seu-servidor.com/ws')
const socket = new WebSocket('wss://echo.websocket.events');
// 2. Quando a conexão é confirmada
socket.onopen = () => {
statusEl.className = 'status-online';
statusEl.textContent = '● Conectado (Full-Duplex)';
adicionarMensagem('Sistema', 'Conectado à sala em tempo real!', 'msg-other');
};
// 3. Recebimento de mensagens vindas do servidor
socket.onmessage = (event) => {
adicionarMensagem('Servidor Echo', event.data, 'msg-other');
};
// 4. Tratamento de encerramento de conexão
socket.onclose = () => {
statusEl.className = 'status-offline';
statusEl.textContent = '○ Conexão Encerrada';
};
// 5. Envio de mensagem pelo usuário
formEl.addEventListener('submit', (e) => {
e.preventDefault();
const texto = inputEl.value.trim();
if (texto && socket.readyState === WebSocket.OPEN) {
// Envia o dado pelo canal TCP aberto
socket.send(texto);
// Exibe no histórico local
adicionarMensagem('Você', texto, 'msg-me');
inputEl.value = '';
}
});
function adicionarMensagem(autor, texto, classe) {
const div = document.createElement('div');
div.className = `msg-bubble ${classe}`;
div.innerHTML = `${autor}: ${texto}`;
messagesEl.appendChild(div);
messagesEl.scrollTop = messagesEl.scrollHeight; // Auto-scroll para a última mensagem
}
5. Boas Práticas: Reconexão Automática e Heartbeat
Diferente de conexões HTTP comuns ou SSE, a especificação básica do WebSocket não reconecta sozinha se o roteador Wi-Fi oscilar. Em sistemas de produção, aplicam-se duas práticas obrigatórias:
-
Heartbeat (Ping/Pong): O cliente envia uma mensagem minúscula (ex:
{"tipo": "ping"}) a cada 25 segundos. Se o servidor não responder com um “pong”, o cliente assume que a conexão caiu silenciosamente e força uma reinicialização. - Reconexão com Backoff Exponencial: Caso o socket seja fechado por erro, a aplicação agenda uma nova tentativa de conexão em 1s, depois em 2s, 4s, 8s, até o teto máximo, impedindo um ataque de negação de serviço (DoS) involuntário contra seu próprio servidor.
🎉 Parabéns! Você Concluiu o Módulo 3!
Com esta lição sobre WebSockets, você finalizou com maestria todas as 15 aulas dedicadas ao HTML5 Moderno & APIs Nativas (Lições 27 a 41).
Você dominou desde a semântica avançada e formulários inteligentes até gráficos com Canvas, vetores SVG, Drag & Drop, Geolocalização, LocalStorage, Web Workers, SSE e WebSockets. Prepare-se para o Módulo 4: Prática, Acessibilidade & Publicação Profissional, onde colocaremos tudo em produção com padrões de acessibilidade WCAG, performance e SEO internacional!
6. Ferramentas Relacionadas & Próximos Passos
Continue seu desenvolvimento explorando as soluções práticas do nosso ecossistema:
- Central do Desenvolvedor Web: Conversores JSON, geradores de dados e testadores de payloads em tempo real.
- Hub Master de Imagens: Utilitários gráficos e otimizadores para avatares de chat.
- Lição 40: Server-Sent Events (SSE): Revise o modelo unidirecional para feeds e notificações.
- Lição 42: Acessibilidade Web & Diretrizes WCAG: O início do Módulo 4 focado na criação de sites acessíveis e inclusivos para todos.
7. Referências Técnicas & Especificações Oficiais
- IETF RFC 6455: The WebSocket Protocol Official Specification
- WHATWG HTML Living Standard: WebSockets API
- MDN Web Docs: The WebSocket API Guide & Tutorials