Networking

TCP/IP & Sockets

TCP/IP é a camada de transporte por trás de cada requisição HTTP, conexão de banco de dados e WebSocket. Sockets são a forma como seu código se comunica diretamente com ela.

intermediate14 min readUpdated 15 de set. de 2026
server.js
js
// server.js
import { createServer } from "node:net";

const server = createServer((socket) => {
  socket.write("hello\n");
  socket.on("data", (data) => {
    console.log("received:", data.toString().trim());
  });
});

server.listen(9000, () => console.log("tcp://localhost:9000"));
Modelo
Em camadas (link, IP, transporte, app)
Endereçamento
Endereço IP + porta
Confiável
TCP
Rápido
UDP
Handshake
SYN, SYN-ACK, ACK
No Node
node:net

Por que importa

Por que o TCP/IP é importante

Transporte confiável

O TCP garante a entrega completa e ordenada, razão pela qual HTTP, bancos de dados e e-mails rodam sobre ele.

Tudo o utiliza

Cada requisição que seu servidor processa chega através de uma conexão TCP, mesmo que um framework esconda os detalhes.

Conexões têm um custo

Abrir uma conexão TCP exige uma viagem de ida e volta (round trip) mais um handshake, por isso reutilizá-las é fundamental.

O panorama completo

As três camadas do modelo

Endereços IP e rotas encaminham pacotes, o TCP torna a entrega confiável e os sockets são a API que seu código utiliza.

IP

Endereçar e rotear

Pacotes carregam endereços de origem e destino e são encaminhados salto a salto (hop by hop).

TCP

Confiabilidade

Números de sequência, confirmações (acknowledgements) e retransmissões transformam pacotes não confiáveis em um fluxo estável.

Sockets

Programar

Um socket é o endpoint do qual seu código lê e para o qual escreve, identificado por endereço e porta.

TCP/IP em resumo

Os conceitos fundamentais

Endereços IP

IPv4 e IPv6 identificam um host na rede.

Portas

Um número que identifica um serviço em um host, como a 443 para HTTPS.

Handshake

SYN, SYN-ACK e ACK estabelecem uma conexão e definem as opções.

Números de sequência

A ordenação e a confirmação tornam a entrega confiável.

Controle de fluxo

Janelas (windows) evitam que um remetente rápido sobrecarregue um receptor lento.

Timeouts

Retransmissão, keep-alive e TIME_WAIT governam o ciclo de vida da conexão.

Uma breve historia

O protocolo que sustenta a internet

  1. 1974

    Proposta do TCP

    Cerf e Kahn descrevem um protocolo para conectar redes diferentes.

    74
  2. 1981

    Padronização do TCP/IP

    O conjunto de protocolos é especificado e posteriormente adotado como o padrão da internet.

    81
  3. 1983

    Mudança da ARPANET

    A rede migra para TCP/IP em um único dia, provando sua viabilidade em escala.

    83
  4. 1993

    Controle de congestionamento

    Algoritmos como o TCP Reno evitam o colapso sob carga pesada.

    93
  5. Hoje

    Ainda a fundação

    O HTTP/3 migra para QUIC sobre UDP, mas o TCP ainda carrega a vasta maioria do tráfego.

    Hoje

O guia completo

TCP/IP & Sockets: Tudo que voce precisa saber

O que é TCP/IP?

TCP/IP é o conjunto de protocolos que sustenta a internet. O IP é responsável pelo endereçamento e roteamento de pacotes entre hosts; o TCP atua acima dele, transformando esses pacotes não confiáveis em um fluxo de bytes ordenado e confiável. Juntos, eles formam a camada de transporte sob o HTTP, bancos de dados, e-mail, WebSockets e quase tudo mais que seu servidor faz.

Raramente você escreverá código TCP diretamente, mas entendê-lo explica muita coisa: por que as conexões são caras, por que o keep-alive é importante, por que um pool de banco de dados tem um limite de tamanho e por que parte do tráfego utiliza UDP em vez disso.

O modelo de camadas

O networking geralmente é descrito em camadas, onde cada uma cuida de uma função específica:

Camada Função Exemplos
Aplicação Significado HTTP, WebSocket, DNS
Transporte Confiabilidade e portas TCP, UDP
Internet Endereçamento e roteamento IP, ICMP
Link Entrega local Ethernet, Wi-Fi

Cada camada utiliza a camada logo abaixo dela. O HTTP não sabe se está trafegando via Ethernet ou Wi-Fi; ele confia no TCP para entregar os bytes, que por sua vez confia no IP para mover os pacotes. Essa separação é o motivo pelo qual a internet consegue suportar tantos tipos diferentes de tráfego.

Endereços IP e portas

Um endereço IP identifica um host, e uma porta identifica um serviço nesse host. Juntos, eles formam um endereço de socket, como 203.0.113.10:443.

  • Endereços IPv4 possuem 32 bits (203.0.113.10); endereços IPv6 possuem 128 bits e são escritos em hexadecimal.
  • Portas abaixo de 1024 são reservadas para serviços conhecidos (well-known services).
  • Clientes recebem uma porta efêmera durante o tempo de vida de uma conexão.
  • Uma conexão é identificada de forma única pela tupla completa: endereço de origem, porta de origem, endereço de destino e porta de destino.

Essa tupla é o motivo pelo qual um servidor consegue aceitar milhares de conexões na porta 443 simultaneamente: a porta de origem de cada cliente é diferente.

O three-way handshake

Antes que qualquer dado flua, o TCP estabelece uma conexão em três etapas:

  1. O cliente envia um SYN com seu número de sequência inicial.
  2. O servidor responde com um SYN-ACK, confirmando o recebimento do cliente e enviando seu próprio número de sequência.
  3. O cliente envia um ACK, e a conexão é estabelecida.

Isso custa um round trip antes do primeiro byte de dados da aplicação, o que representa um custo real de latência. O TLS adiciona outro round trip (ou dois), e o DNS pode adicionar mais um antes disso. O reuso de conexão existe especificamente para evitar pagar esses custos repetidamente.

Confiabilidade e controle de fluxo

O TCP garante a confiabilidade por meio de alguns mecanismos:

  • Números de sequência ordenam os bytes, permitindo que o receptor os remonte corretamente.
  • Acknowledgements confirmam o recebimento, e dados não confirmados são retransmitidos.
  • Checksums detectam corrupção de dados.
  • Controle de fluxo utiliza uma janela de recebimento para que um remetente rápido não sobrecarregue um receptor lento.
  • Controle de congestionamento adapta a taxa de envio à rede, evitando o colapso.

O resultado é um fluxo de bytes que chega completo e em ordem, ao custo de certa latência e overhead.

UDP: a alternativa rápida

O UDP não é orientado à conexão. Ele envia datagramas sem handshake, sem ordenação e sem retransmissão. Isso pode parecer pior, mas para algumas cargas de trabalho é a melhor opção:

  • A latência importa mais do que a perfeição: vídeo ao vivo, voz e jogos preferem um frame perdido a um frame atrasado.
  • A aplicação gerencia a confiabilidade: o QUIC, que alimenta o HTTP/3, constrói sua própria camada de confiabilidade sobre o UDP.
  • Consultas pequenas e stateless: o DNS tradicionalmente usa UDP porque uma única requisição e resposta cabem em um único datagrama.

Escolha TCP quando a precisão e a ordenação forem fundamentais, e UDP quando você precisar de velocidade e puder tolerar perdas.

Sockets no Node.js

O Node expõe TCP através do node:net e UDP através do node:dgram. Um servidor TCP fornece a você um socket por conexão.

// echo.js
import { createServer } from "node:net";

const server = createServer((socket) => {
  socket.setKeepAlive(true, 10_000);
  socket.setTimeout(30_000);
  socket.on("timeout", () => socket.destroy());

  socket.on("data", (data) => socket.write(data));
  socket.on("error", (err) => console.error(err));
});

server.listen(9000);

Sockets são streams: você lê eventos data e escreve com socket.write(). Como o TCP é um fluxo de bytes sem limites de mensagem, os protocolos de aplicação devem definir seu próprio enquadramento (framing), e é por isso que o HTTP possui headers com comprimentos de conteúdo e o WebSockets possui frames.

Ciclo de vida e ajuste de conexão

  • Keep-alive reutiliza conexões, evitando o handshake em cada requisição.
  • Pools limitam o número de conexões simultâneas a um banco de dados ou serviço.
  • Timeouts fecham conexões ociosas ou travadas para que os recursos sejam liberados.
  • TIME_WAIT é um estado normal após o fechamento, mas o excesso de conexões de curta duração pode esgotar as portas.
  • Backpressure: socket.write() retorna false quando o buffer está cheio, e você deve aguardar por drain.

A maior parte do ajuste em produção consiste em reutilizar conexões e limitar a concorrência, e não em alterar parâmetros do kernel.

Melhores práticas

  • Reutilize conexões com keep-alive ou um pool.
  • Configure timeouts e keep-alive em conexões de longa duração.
  • Limite a concorrência para não esgotar sockets ou descritores de arquivo (file descriptors).
  • Trate erros e backpressure em cada socket.
  • Use TCP, a menos que tenha um motivo específico para usar UDP.
  • Entenda que o TCP é um fluxo de bytes (byte stream) e defina seu próprio framing.
  • Monitore o TIME_WAIT e a contagem de conexões como um sinal de rotatividade de conexões (connection churn).

Erros comuns

  • Abrir uma nova conexão para cada requisição.
  • Presumir que o TCP preserva os limites das mensagens (message boundaries).
  • Ignorar o backpressure de socket.write() e fazer o buffering de dados ilimitados.
  • Manter conexões de longa duração sem keep-alive ou timeouts.
  • Definir tamanhos de pool muito maiores do que o banco de dados consegue suportar.
  • Optar por UDP quando a confiabilidade é realmente importante.

Próximos passos

O TCP/IP é a camada sobre a qual tudo mais é construído. Avance com o guia de HTTP, entenda os fundamentos de rede em Como a Internet Funciona e explore conexões persistentes com WebSockets. Depois, inspecione conexões reais na sua máquina com ss ou netstat enquanto seu servidor processa o tráfego.

Escolhendo um transporte

O TCP garante a entrega ordenada ao custo de handshakes e retransmissões. O UDP troca a confiabilidade por menor latência.

TCP
// reliable, ordered stream
const socket = net.connect(9000, "localhost");
socket.write("GET / HTTP/1.1\r\n\r\n");
UDP
// fast, no delivery guarantee
const socket = dgram.createSocket("udp4");
socket.send(Buffer.from("ping"), 9001, "localhost");

Reutilizando conexões

Abrir uma conexão por requisição paga o custo do handshake toda vez. O keep-alive reutiliza uma única conexão para várias requisições.

Preferir
const agent = new http.Agent({
  keepAlive: true,
  maxSockets: 50,
});

fetch(url, { agent });
Evitar
// a fresh connection and
// handshake for every call
for (const url of urls) {
  await fetch(url);
}

Perguntas frequentes

Perguntas frequentes

Keep learning

Related topics from the roadmap.

$ comecar a aprender

Pronto para aprender TCP/IP & Sockets?

Nosso tutorial interativo te guia por TCP/IP & Sockets passo a passo — com quizzes e codigo real que voce pode executar no navegador.