- TCP (Transmission Control Protocol) é o protocolo central da internet que possibilita transmissão de dados confiável e com ordem garantida mesmo em ambientes de rede instáveis
- Enquanto o IP cuida apenas da entrega de dados entre hosts, o TCP realiza comunicação entre processos baseada em portas e faz recuperação de erros, retransmissão e controle de ordem
- Por meio de controle de fluxo (flow control) e controle de congestionamento (congestion control), ajusta a transmissão para não ultrapassar os limites do buffer de recepção ou da largura de banda da rede
- Com exemplos de um servidor TCP simples e de um servidor HTTP implementados em C, o texto explica de forma concreta a criação de sockets, bind, listen, aceitação de conexão e o processo de envio e recebimento
- A estrutura interna do TCP, como números de sequência e ACK, janela, checksum e flags (SYN/ACK/FIN/RST), é a base essencial que permite o funcionamento estável da internet atual
Necessidade e papel do TCP
- O IP é responsável apenas pela entrega de pacotes entre hosts, e para a comunicação entre processos é necessária uma camada de transporte como TCP/UDP
- O endereço IP é comparado a um “prédio” e a porta a um “apartamento”, com cada aplicação se comunicando após fazer bind em uma porta
- O TCP oculta instabilidades da rede, como perda, duplicação e inversão de ordem de pacotes, e garante confiabilidade com retransmissão e checksum
- Os roteadores permanecem simples, e a confiabilidade é tratada nas duas extremidades da comunicação, reduzindo a complexidade da infraestrutura de rede
- Graças a essa estrutura, serviços centrais da internet como HTTP, SMTP e SSH funcionam de forma estável
Controle de fluxo e controle de congestionamento
- O lado receptor armazena temporariamente os dados por meio do buffer de recepção (receive buffer) do kernel, cujo tamanho é configurado por
net.ipv4.tcp_rmem
- O lado emissor recebe pelo campo janela (window) a quantidade de dados que o receptor pode aceitar e ajusta o volume transmitido
- Para evitar congestionamento (congestion) causado por diferenças de largura de banda em toda a rede, o TCP introduz algoritmos de controle de congestionamento
- Após o evento de congestion collapse de 1986, foi adicionado o mecanismo de back-off
Exemplos de servidor TCP e servidor HTTP
- Um servidor echo TCP básico escrito em C recebe a entrada do cliente e a reenvia com o prefixo “you sent:”
- Usa a API de sockets Berkeley, como
socket(), bind(), listen(), accept(), send() e recv()
- Enquanto o servidor está em
sleep(), os dados do cliente ficam aguardando no buffer de recepção e depois são processados em sequência
- Em um exemplo simples de servidor HTTP/1.1, o servidor aceita requisições por uma conexão TCP e envia o cabeçalho
HTTP/1.1 200 OK e o corpo da resposta
- Conta o número de requisições com
i, e ao executar curl localhost:8080 retorna uma resposta no formato “[1] Yo, I am a legit web server”
Estrutura do segmento TCP e campos principais
- Um segmento TCP é composto por porta de origem e de destino, número de sequência, número ACK, tamanho da janela, checksum e flags
- As portas recebem 16 bits cada, permitindo o uso de até 64K portas
- A conexão é identificada por uma 5-tupla:
(protocolo, IP de origem, porta de origem, IP de destino, porta de destino)
- O número de sequência indica o intervalo de bytes transmitidos, e o número ACK indica os bytes recebidos com sucesso
- Se houver dados ausentes, o ACK para nesse ponto e, após a retransmissão, é atualizado como ACK cumulativo
- Os bits de flag controlam o estado da conexão
SYN/ACK estabelecem a conexão por meio do 3-way handshake
FIN encerra a conexão por meio do 4-way handshake
RST desfaz a conexão imediatamente em caso de encerramento anormal ou erro
- O campo window indica a quantidade de dados que podem ser recebidos, e o estado do buffer (
rb131072, tb16384) pode ser verificado com o comando ss
- O checksum detecta erros ao somar unidades de 16 bits dentro do segmento
Conclusão
- O TCP garante confiabilidade, ordem e integridade, permitindo que as aplicações funcionem corretamente mesmo em um ambiente de internet instável
- Há décadas, era difícil até transmitir alguns KB, mas hoje a streaming em 4K se tornou algo cotidiano
- A sofisticação do design e da implementação do TCP é a base do crescimento contínuo da internet
1 comentários
Comentários do Hacker News
Se você tentar criar um fluxo de dados confiável sobre uma camada de datagramas não confiável, o resultado acaba ficando quase idêntico ao TCP
As limitações iniciais do TCP eram uma janela pequena, tratamento insuficiente de perda de pacotes e o fato de gerenciar apenas um único fluxo
Para resolver esses problemas, surgiram o SCTP e o QUIC
Os algoritmos de controle de congestionamento não são parte do protocolo, mas sim código que roda em ambos os lados de cada conexão
Os algoritmos iniciais (Reno, Vegas etc.) eram simples, mas suficientemente eficazes, e desde então continuam as pesquisas sobre buffers grandes, RTT longo, justiça na rede e outros temas
No passado, cheguei a criar em JavaScript uma biblioteca capaz de controlar priorização e cancelamento de vários downloads em um único fluxo
Usei isso com um script do GreaseMonkey para pré-carregar em segundo plano miniaturas de um site de namoro, fazendo o pré-carregamento conforme a posição de rolagem
No fim, isso reduziu a carga no servidor e melhorou a experiência do usuário
Curiosamente, compartilhei esse script com uma das combinações, e estamos juntos até hoje — era praticamente um Tinder antes do Tinder
O TCP é uma estrutura que fornece um circuito virtual sobre uma rede de comutação por pacotes, e a ideia de implementar confiabilidade por retransmissão veio da rede francesa Cylades
Um atacante pode injetar dados em qualquer ponto da rede ou derrubar a conexão com um pacote RST
Bloquear RST com firewall aumenta a estabilidade, mas ataques de dessincronização com números de sequência forjados ainda continuam possíveis
Por isso, toda aplicação precisa implementar uma função de retomada em uma conexão separada, além de carregar junto o problema do slow start do TCP
Também acho ineficiente o próprio conceito de separar endereços e portas
Por exemplo, em DNS over TLS (DoT) é possível enviar várias consultas ao mesmo tempo por uma única conexão TCP e receber as respostas fora de ordem
Isso é mais eficiente e mais educado do que abrir várias conexões
Não sei se o QUIC será mais rápido, mas o suporte de servidor ainda é limitado
O HTTP/1.1 pipelining também faz algo parecido, mas as respostas chegam em sequência
Mas muitas aulas universitárias não destacam isso, então muita gente acaba achando que o TCP tem apenas um único algoritmo
Gostaria de perguntar se alguém tem carinho pelo SCTP
O SCTP é um protocolo que combina a orientação a mensagens do UDP com a confiabilidade do TCP, com suporte a multistreaming e multihoming
Como vários fluxos independentes podem ser transmitidos em paralelo, dá para enviar simultaneamente o texto e as imagens de uma página web
Para mais detalhes, veja Wikipedia: Stream Control Transmission Protocol
No fim, a melhor resposta é uma camada de confiabilidade sobre UDP, ou seja, o QUIC
Eu tinha curiosidade se era possível enviar pacotes diretamente só com IP
Parecia que os roteadores intermediários rejeitariam pacotes que não fossem TCP nem UDP
No IPv4, basta especificar um dos números de 0 a 255 da lista de números de protocolo da IANA
Os roteadores centrais não inspecionam esse campo, mas NATs ou equipamentos de ISPs podem inspecionar
Entre dois servidores Linux, também é possível se comunicar usando números experimentais (253, 254)
Protocolos como IPsec, GRE e L2TP também não são TCP/UDP
Em firewalls corporativos ou ambientes com NAT, protocolos arbitrários podem ser bloqueados
O NAT quebrou o princípio end-to-end, e no fim as pessoas passaram a colocar tudo sobre TCP, UDP ou até sobre HTTP
No máximo há impacto na redução de entropia do hash de ECMP
No fim, a questão é se o outro lado entende esse protocolo
Números de porta são apenas identificadores de serviço dentro do nó
O RUDP (Plan9) era um excelente meio-termo entre TCP e UDP
Veja Reliable User Datagram Protocol
Como o TCP virou o padrão, ele acabou sendo usado de forma automática até quando não era necessário confiabilidade ou garantia de ordem
Agora, com a disseminação do HTTP/3 (baseado em QUIC), pode ser que a situação melhore
Mas o QUIC é muito mais complexo, e esse poder extra só é útil para alguns casos
Uma camada de criptografia simples no estilo UDP + WireGuard pode ser uma alternativa melhor
O TCP é uma das grandes invenções da humanidade, mas não previu o domínio das redes semiconectadas (baseadas em NAT)
os engenheiros da época provavelmente perguntariam por que criar algo tão complicado de propósito
No fim, a atual estrutura de links assimétricos e a distinção cliente-servidor vieram desse tipo de ideia
Os algoritmos de controle de congestionamento do TCP têm efeitos interessantes que muitos desenvolvedores desconhecem
Quando se envia dados em uma nova conexão, a transmissão inicial é lenta, e o aumento de velocidade é determinado pela latência
Em datacenters, reduzir o RTT em poucos microssegundos já pode trazer grandes ganhos de velocidade
A maioria das stacks TCP calcula esse aumento por segmento, e não por byte, então usar jumbo frames pode fazer a velocidade subir 6 vezes mais rápido
Por isso a AWS investe muito em baixa latência de switching e suporte a jumbo frames
Especialistas fazem esse tipo de ajuste, mas a maioria só se pergunta por que não consegue 10 Gbps em um link de 10 Gbps
Criar seu próprio protocolo sobre IP era algo muito simples
Até uns 15 anos atrás, dava para experimentar montando pacotes manualmente em Python