W3docs

API WebSocket do JavaScript

Aprenda a API WebSocket do JavaScript: ciclo de vida da conexão, readyState, envio de texto, JSON e dados binários, reconexão e segurança, com exemplo de Echo Chat executável.

Introdução à Tecnologia WebSocket

WebSocket é um protocolo que fornece um canal de comunicação full-duplex (bidirecional) entre o navegador e um servidor por meio de uma única conexão TCP de longa duração. Uma vez que a conexão está aberta, qualquer lado pode enviar uma mensagem a qualquer momento sem esperar que o outro solicite — algo que o HTTP comum não consegue fazer.

Esta página aborda o que os WebSockets resolvem, o ciclo de vida da conexão, o envio de dados de texto e binários, o trabalho com mensagens JSON, reconexão, segurança e quando usar uma biblioteca em vez da API bruta. Construímos tudo em torno de um exemplo de Echo Chat executável.

Por que WebSockets em vez de HTTP?

Com o HTTP comum (incluindo a Fetch API e o XMLHttpRequest), o cliente deve iniciar cada troca. Para obter atualizações em tempo real, você precisa usar polling — perguntar repetidamente "há algo novo?" — o que desperdiça largura de banda e aumenta a latência. Os WebSockets invertem isso: o servidor pode enviar dados no instante em que tiver algo, com quase nenhuma sobrecarga por mensagem.

AbordagemDireçãoSobrecargaMelhor para
Requisição/resposta HTTPO cliente pergunta, o servidor respondeCabeçalhos completos por requisiçãoBuscas únicas, REST APIs
PollingO cliente pergunta em intervalosMuitas requisições desnecessáriasAtualizações simples e de baixa frequência
WebSocketAmbos enviam livrementeUm handshake, frames pequenosChat, feeds ao vivo, jogos, dashboards

Use WebSockets quando o servidor precisar falar primeiro ou quando as mensagens fluírem constantemente: chat, jogos multiplayer, editores colaborativos, tickers de negociação e dashboards ao vivo. Para atualizações ocasionais e unidirecionais do servidor para o cliente apenas, Server-Sent Events ou a Push API podem ser mais simples.

O Ciclo de Vida da Conexão WebSocket

Você abre uma conexão passando uma URL ws:// (simples) ou wss:// (criptografada) para o construtor WebSocket. A conexão então passa por quatro estados expostos por socket.readyState:

ConstanteValorSignificado
WebSocket.CONNECTING0Handshake em andamento (estado inicial)
WebSocket.OPEN1Pronto para enviar e receber
WebSocket.CLOSING2Um fechamento foi solicitado
WebSocket.CLOSED3Conexão fechada ou falhou ao abrir

Você reage às transições com quatro eventos: open, message, error e close. A regra principal é que você só pode chamar socket.send() enquanto readyState for OPEN — enviar antes que open seja disparado gera um erro.

const socket = new WebSocket("wss://echo.websocket.events");

socket.addEventListener("open", () => {
  console.log("open, readyState =", socket.readyState); // 1
  socket.send("hello");
});

socket.addEventListener("message", (event) => {
  console.log("received:", event.data); // "hello" (echoed back)
});

socket.addEventListener("close", (event) => {
  console.log("closed, code =", event.code); // e.g. 1000
});

Configurando o Echo Chat WebSocket

Estrutura HTML Básica

Primeiro, estabelecemos a interface do usuário com HTML que inclui uma área de exibição de mensagens, campo de entrada e botões de controle.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>WebSocket Echo Chat</title>
</head>
<body>
    <textarea id="chatBox" readonly style="width: 100%; height: 300px"></textarea><br />
    <input type="text" id="messageInput" placeholder="Type a message..." style="width: 75%" />
    <button onclick="sendMessage()">Send</button>
    <button onclick="closeConnection()">Close Connection</button>
</body>
</html>

Integrando WebSocket com JavaScript

O JavaScript para gerenciar a comunicação WebSocket é fundamental para habilitar interações em tempo real.

<script>
    // Accessing the chat box and message input elements from the HTML.
    const chatBox = document.getElementById("chatBox");
    const messageInput = document.getElementById("messageInput");

    // Establishing a WebSocket connection to the echo server.
    const socket = new WebSocket("wss://echo.websocket.events");

    // When the connection is open, display a connected message in the chat box.
    socket.addEventListener("open", function (event) {
        chatBox.value += "Connected to the echo server\n";
    });

    // Handle incoming messages by adding them to the chat box.
    socket.addEventListener("message", function (event) {
        chatBox.value += "Echoed back: " + event.data + "\n";
    });

    // Handle connection errors.
    socket.addEventListener("error", function (event) {
        chatBox.value += "Connection error occurred.\n";
    });

    // Handle connection closure.
    socket.addEventListener("close", function (event) {
        chatBox.value += "Connection closed. Code: " + event.code + "\n";
    });

    // Function to send a message when the send button is clicked.
    function sendMessage() {
        const message = messageInput.value; // Get the message from the input field.
        if (!message) return; // If there's no message, don't do anything.
        socket.send(message); // Send the message to the server.
        chatBox.value += "You: " + message + "\n"; // Show the message in the chat box.
        messageInput.value = ""; // Clear the message input field.
    }

    // Function to close the WebSocket connection.
    function closeConnection() {
        if (socket.readyState === WebSocket.OPEN) {
            socket.close(1000, "The user closed the connection"); // Close the connection normally.
            chatBox.value += "Connection closed by user\n"; // Inform the user in the chat box.
        } else {
            alert("Connection is not open or already closed."); // Alert if the connection can't be closed.
        }
    }

    // Ensure the WebSocket is closed properly when the webpage is closed or reloaded.
    window.addEventListener("beforeunload", function () {
        if (socket.readyState === WebSocket.OPEN) {
            socket.close(1000, "The page is unloading"); // Close the connection normally.
        }
    });
</script>

Este script configura um recurso de chat em uma página web que se conecta a um servidor usando WebSockets. Veja uma explicação simples de suas partes:

  1. Acessando Elementos HTML: O script obtém a caixa de chat e a caixa de entrada de mensagens da página web para poder interagir com elas.
  2. Conexão WebSocket: Ele abre uma conexão com um servidor que ecoa as mensagens de volta. Isso significa que tudo o que você enviar para este servidor será enviado de volta para você.
  3. Exibindo o Status da Conexão: Quando a conexão é estabelecida com sucesso, uma mensagem é exibida na caixa de chat informando que a conexão com o servidor de eco foi estabelecida.
  4. Tratando Mensagens Recebidas: Quaisquer mensagens que retornem do servidor são adicionadas à caixa de chat, mostrando que o servidor ecoou as mensagens.
  5. Enviando Mensagens: Há uma função para enviar mensagens digitadas na caixa de entrada. Se houver texto, ele o envia para o servidor e depois o exibe na caixa de chat como sua mensagem.
  6. Fechando a Conexão: Há também uma função para fechar a conexão WebSocket quando necessário, como quando o usuário decide fechá-la ou quando a página web está sendo fechada.

Esta configuração permite comunicação em tempo real com o servidor e ajuda a testar e demonstrar como funcionam os aplicativos de mensagens.

E agora vamos juntar tudo e ver em ação:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>WebSocket Echo Chat</title>
  </head>

  <body>
    <textarea id="chatBox" readonly style="width: 100%; height: 300px">
    </textarea>
    <br />
    <input
      type="text"
      id="messageInput"
      placeholder="Type a message..."
      style="width: 75%"
    />
    <button onclick="sendMessage()">Send</button>
    <button onclick="closeConnection()">Close Connection</button>
  </body>
  <script>
    const chatBox = document.getElementById("chatBox");
    const messageInput = document.getElementById("messageInput");

    const socket = new WebSocket("wss://echo.websocket.events");

    socket.addEventListener("open", function (event) {
      chatBox.value += "Connected to the echo server\n";
    });

    socket.addEventListener("message", function (event) {
      chatBox.value += "Echoed back: " + event.data + "\n";
    });

    socket.addEventListener("error", function (event) {
      chatBox.value += "Connection error occurred.\n";
    });

    socket.addEventListener("close", function (event) {
      chatBox.value += "Connection closed. Code: " + event.code + "\n";
    });

    function sendMessage() {
      const message = messageInput.value;
      if (!message) return;
      socket.send(message);
      chatBox.value += "You: " + message + "\n";
      messageInput.value = "";
    }

    function closeConnection() {
      if (socket.readyState === WebSocket.OPEN) {
        socket.close(1000, "The user closed the connection");
        chatBox.value += "Connection closed by user\n";
      } else {
        alert("Connection not open or already closed.");
      }
    }

    window.addEventListener("beforeunload", function () {
      if (socket.readyState === WebSocket.OPEN) {
        socket.close(1000, "The page is unloading");
      }
    });
  </script>
</html>

No exemplo acima, assim que você se conecta ao servidor, pode começar a enviar mensagens e receberá exatamente o que digitou, ecoado de volta para você. Se você clicar no botão 'Close Connection', a conexão WebSocket será encerrada e você não receberá mais mensagens ecoadas.

Recursos e Técnicas Avançados de WebSocket

Enviando Dados Estruturados como JSON

Aplicativos reais raramente enviam strings simples — eles enviam objects. Como o canal de transmissão só suporta texto ou binário, você serializa objects com JSON.stringify() antes de enviar e os analisa com JSON.parse() na chegada. Veja Trabalhando com JSON para mais informações sobre este formato.

// Sending an object
const payload = { type: "chat", user: "Ann", text: "Hi!" };
socket.send(JSON.stringify(payload));

// Receiving and parsing it
socket.addEventListener("message", (event) => {
  const msg = JSON.parse(event.data);
  console.log(msg.user + ": " + msg.text); // "Ann: Hi!"
});

Um padrão comum é um campo type que permite que uma conexão multiplexe muitos tipos de mensagens — chat, presence, typing, entre outros — cada um tratado por seu próprio bloco.

Manipulando Dados Binários

WebSockets não se limitam a texto. Eles também podem carregar frames binários, úteis para áudio, imagens ou estado de jogo. Defina socket.binaryType para controlar como os dados binários recebidos chegam — "blob" (o padrão) ou "arraybuffer".

socket.binaryType = "arraybuffer";

// Send raw bytes
const bytes = new Uint8Array([72, 73]); // "HI"
socket.send(bytes);

socket.addEventListener("message", (event) => {
  if (typeof event.data === "string") {
    console.log("text frame:", event.data);
  } else {
    const view = new Uint8Array(event.data);
    console.log("binary frame, length:", view.length);
  }
});

Reconexão Automática

Redes caem. O WebSocket bruto não reconecta por conta própria — quando close é disparado inesperadamente, você deve reabrir a conexão manualmente, idealmente com um recuo crescente (exponencial) para não sobrecarregar o servidor.

let delay = 1000; // start at 1 second

function connect() {
  const socket = new WebSocket("wss://echo.websocket.events");

  socket.addEventListener("open", () => {
    delay = 1000; // reset back-off after a successful connection
  });

  socket.addEventListener("close", () => {
    setTimeout(connect, delay);
    delay = Math.min(delay * 2, 30000); // cap at 30 seconds
  });
}

connect();

Implementando Segurança em WebSocket

A segurança é fundamental ao lidar com WebSockets:

  • Use WSS: Sempre use WebSocket Secure (WSS), que criptografa os dados transmitidos entre o cliente e o servidor.
  • Autenticação: Implemente autenticação baseada em token para garantir que apenas usuários autorizados possam estabelecer conexões WebSocket.
  • Validação: Valide adequadamente todos os dados enviados ao servidor para evitar vulnerabilidades web comuns, como XSS ou injeção SQL.

WebSocket e o Padrão Pub/Sub

O padrão publish/subscribe é um modelo popular em serviços de dados em tempo real, onde as mensagens são transmitidas por um canal. Serviços WebSocket como PubNub oferecem APIs que suportam o modelo pub/sub, aprimorando as capacidades do WebSocket ao gerenciar conexões, fornecer criptografia de dados e facilitar transmissões baseadas em canais.

Bibliotecas e Frameworks WebSocket

Várias bibliotecas JavaScript tornam o trabalho com WebSockets mais fácil e robusto:

  • Socket.IO: Fornece recursos adicionais como reconexão automática, tratamento de eventos e gerenciamento de salas.
  • WebSocket-Node: Uma implementação de servidor WebSocket para Node.js.
  • ReconnectingWebSocket: Uma pequena biblioteca que adiciona recursos de reconexão a WebSockets simples.

Conclusão

A tecnologia WebSocket é um bloco de construção fundamental para o desenvolvimento de aplicativos web interativos e em tempo real. Ao integrar WebSockets em seus aplicativos, você habilita a interação direta e bidirecional entre clientes e servidores. Este guia percorreu o ciclo de vida da conexão, o exemplo de Echo Chat, mensagens JSON e binárias, reconexão e segurança — o suficiente para construir recursos em tempo real robustos.

Veja Também

  • Fetch API — para requisições HTTP únicas quando você não precisa de um canal ativo.
  • XMLHttpRequest — a API de requisição mais antiga sobre a qual WebSockets e Fetch se baseiam conceitualmente.
  • Push API — mensagens do servidor para o cliente mesmo quando a página está fechada.
  • Trabalhando com JSON — o formato padrão para mensagens WebSocket estruturadas.

Prática

Prática
Quais são as principais vantagens de usar WebSockets em aplicativos web?
Quais são as principais vantagens de usar WebSockets em aplicativos web?
Prática
Em qual readyState você pode chamar socket.send() com segurança?
Em qual readyState você pode chamar socket.send() com segurança?
Prática
Como você envia um object JavaScript por um WebSocket?
Como você envia um object JavaScript por um WebSocket?
Was this page helpful?