⚡
UDP, QUIC e HTTP/3: por que Google jogou TCP fora
⏱ 14 min de leitura·+70 XP
UDP é o protocolo sem garantias — sem conexão, sem ordem, sem retransmissão. Isso que o torna ideal para tempo real. QUIC reimplementa as partes boas do TCP em cima do UDP, sem carregar suas limitações de décadas. HTTP/3 é a versão da web sobre QUIC.
UDP: o protocolo sem garantias
import socket
import time
# UDP: User Datagram Protocol
# Header mínimo: src_port(2) + dst_port(2) + length(2) + checksum(2) = 8 bytes
# TCP header: 20+ bytes. UDP: 8 bytes.
# Sem: conexão, confirmação, ordering, controle de fluxo, congestionamento
# Servidor UDP simples:
def udp_server(host: str = "0.0.0.0", port: int = 5005):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((host, port))
print(f"UDP server ouvindo em {host}:{port}")
while True:
data, addr = sock.recvfrom(65535) # máximo de um datagrama UDP
print(f"De {addr}: {data.decode()}")
sock.sendto(b"ok", addr)
# Cliente UDP simples:
def udp_client(host: str, port: int, message: str):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(1.0)
sock.sendto(message.encode(), (host, port))
try:
resp, _ = sock.recvfrom(1024)
return resp.decode()
except socket.timeout:
return None # datagrama perdido — sem retransmissão automática
# DNS usa UDP (porta 53):
# Query simples (< 512 bytes) → UDP
# Respostas grandes (DNSSEC) → TCP (truncated flag indica necessidade)
# dig usa UDP por padrão; dig +tcp força TCP
# Datagramas UDP não garantem:
# 1. Entrega (pode ser descartado por router/firewall)
# 2. Ordem (seg 1 pode chegar depois de seg 2)
# 3. Integridade (checksum optional no IPv4 — pode ser zerado)
# 4. Unicidade (pode duplicar em retransmissões de L2)
# Casos onde UDP ganha:
# - RTT único (DNS, DHCP) — mais rápido que TCP handshake
# - Dados em tempo real (voz, vídeo) — dado velho inútil
# - Broadcast/multicast (TCP é ponto-a-ponto apenas)
# - Jogos online (posição, inputs — dado velho descartável)QUIC: TCP reimaginado sobre UDP
| Característica | TCP+TLS | QUIC (UDP) |
|---|---|---|
| Handshake nova conexão | 3 RTTs (TCP+TLS 1.3) | 1 RTT |
| Handshake reconexão | 1 RTT (TLS session) | 0 RTT |
| Múltiplos streams | Não (1 stream por conexão) | Sim (independentes) |
| HoL blocking | Sim (transporte) | Não (por stream) |
| Mobilidade de IP | Não (quebra conexão) | Sim (Connection ID) |
| Header encryption | Não | Sim (IP+porta apenas visíveis) |
| User-space stack | Não (kernel) | Sim (flexível, iterável) |
# QUIC (RFC 9000): protocolo de transporte multiplexado e seguro # Implementado em userspace — facilita evolução sem mudança de kernel # Estrutura de um pacote QUIC: # [UDP header 8B] [QUIC header: Connection ID + packet num + version] [frames] # Frames QUIC dentro do payload (criptografados): # - STREAM: dados de um stream específico # - ACK: confirmação de pacotes recebidos # - CRYPTO: handshake TLS 1.3 # - RESET_STREAM: cancela um stream individual # - CONNECTION_CLOSE: fecha a conexão # Streams independentes: a chave do HoL blocking fix # Stream 1: HTML # Stream 2: CSS ← se perda de pacote QUIC aqui # Stream 3: JS ← este stream NÃO é bloqueado # Stream 4: imagem ← este stream NÃO é bloqueado # Diferente do TCP onde perda bloqueia TODOS os dados subsequentes # Connection ID: permite mobilidade de IP # TCP identifica conexão por (src_ip, src_port, dst_ip, dst_port) # Mudar de Wi-Fi para 4G → src_ip muda → conexão TCP quebra # QUIC usa Connection ID opaco (64 bits) — não muda com IP # Celular muda de rede → QUIC continua sem re-handshake # 0-RTT connection resumption: # 1ª conexão: 1 RTT handshake. Servidor envia "session ticket" criptografado. # 2ª conexão: cliente envia dados da aplicação COM o primeiro pacote QUIC. # Servidor decripta session ticket → recupera chaves de sessão → decripta dados. # Total: 0 RTTs adicionais de handshake (limitado a dados idempotentes) # Implementações QUIC em Python: # aioquic: https://github.com/aiortc/aioquic # Exemplo de cliente HTTP/3: # python -m aioquic.examples.http3_client https://quic.nginx.org/ # Verificar se site suporta QUIC/HTTP3: # curl --http3 https://cloudflare.com -I # chrome://net-internals/#quic (Chrome DevTools)
UDP para tempo real: RTP e WebRTC
# RTP (Real-time Transport Protocol, RFC 3550):
# Roda sobre UDP. Adiciona apenas o que importa para mídia:
# - Sequence number (16 bits): detectar perda e reordenação
# - Timestamp: sincronização de playback (não wall clock)
# - SSRC: identifica a fonte de mídia
# NÃO adiciona: retransmissão, controle de congestionamento
# Controle de qualidade: RTCP (companion) reporta jitter, perda, RTT
import socket
import struct
import time
# Header RTP (12 bytes):
# V(2) P(1) X(1) CC(4) M(1) PT(7) | Sequence(16) | Timestamp(32) | SSRC(32)
def build_rtp_header(seq: int, timestamp: int, ssrc: int, payload_type: int = 96) -> bytes:
"""Constrói header RTP mínimo."""
version = 0b10 # RTP version 2
first_byte = (version << 6) # sem padding, sem extensão, CC=0
second_byte = payload_type & 0x7F # PT sem marker
return struct.pack("!BBHII", first_byte, second_byte, seq, timestamp, ssrc)
# WebRTC: P2P real-time usando DTLS-SRTP sobre UDP
# DTLS: TLS adaptado para datagramas (handles packet loss/reorder)
# SRTP: RTP com criptografia (DTLS negocia chaves)
# ICE: encontra o melhor caminho (direct UDP, STUN, TURN)
# ICE (Interactive Connectivity Establishment):
# 1. Gather candidates: endereço local, STUN (NAT reflexive), TURN (relay)
# 2. Connectivity check: testa cada par de candidatos
# 3. Nominate: escolhe o melhor caminho (preferência: direto > STUN > TURN)
# STUN (Session Traversal Utilities for NAT):
# Pergunta para servidor público: "qual é meu IP:porta externa?"
# Servidor responde com o IP:porta que o NAT mapeou
# TURN (Traversal Using Relays around NAT):
# Relay para casos onde conexão direta falha (NAT simétrico)
# Custo: tráfego passa pelo servidor relay
# Jitter buffer: compensa variação de latência (jitter)
# Atrasa reprodução em X ms para ter buffer de frames
# Trade-off: menor atraso vs maior conforto (sem glitches)
# WebRTC adapta o jitter buffer dinamicamente✅
Modelo mental: UDP = enviar e esquecer (sem garantias, mas 8 bytes de overhead e zero latência de handshake). Ideal quando dado velho é inútil (vídeo ao vivo, jogos, DNS). QUIC = TCP reimaginado sobre UDP: 0-1 RTT de handshake, streams independentes (sem HoL blocking), mobilidade de IP (Connection ID), header criptografado, implementado em userspace. HTTP/3 roda sobre QUIC — já usado por 25%+ dos sites do mundo (Cloudflare, Google, Meta).
💡
Próximo: HTTP/1.1, /2, /3 — como cada versão resolveu limitações da anterior e o que muda na prática.
🧩
Quiz rápido
3 perguntas · Acerte tudo e ganhe o badge 🎯 Gabarito
Continue lendo