⚡ Curso de HTML • Web-ZoneWare

HTML5 WebSockets: Guia de Comunicação Real | Web Academy

Lição 41 de 50

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.

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):

CODE 13 linhas
<!-- 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:

HTML5 20 linhas
<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>
CSS3 85 linhas
.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;
}
JavaScript 50 linhas
// 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
}
🧪 Quer testar o chat WebSocket com eco bidirecional agora?
⚡ Abrir no Playground IDE →

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:

  1. 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.
  2. 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:

7. Referências Técnicas & Especificações Oficiais


Rolar para cima