🧠FFVAcademy

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ísticaTCP+TLSQUIC (UDP)
Handshake nova conexão3 RTTs (TCP+TLS 1.3)1 RTT
Handshake reconexão1 RTT (TLS session)0 RTT
Múltiplos streamsNão (1 stream por conexão)Sim (independentes)
HoL blockingSim (transporte)Não (por stream)
Mobilidade de IPNão (quebra conexão)Sim (Connection ID)
Header encryptionNãoSim (IP+porta apenas visíveis)
User-space stackNã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