Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

01 - Serviço Confiável

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

Serviço Confiável

O Serviço Confiável é a função primária e mais complexa do modelo de Circuito Virtual na Camada de Transporte (ex: TCP). Enquanto a Camada de Rede subjacente (IP) é inerentemente não confiável ("melhor esforço"), o serviço confiável da Camada de Transporte atua como uma camada de abstração que esconde todas as falhas da rede da aplicação.

Para a aplicação, o serviço confiável garante que o canal de comunicação seja perfeito: tudo o que é enviado é recebido, na ordem correta, sem corrupção e sem duplicação. Para alcançar isso sobre uma infraestrutura falha, o protocolo de transporte implementa um conjunto rigoroso de mecanismos de controle de erro, recuperação e gerenciamento de estado.

1. As Quatro Garantias Fundamentais

Um serviço é considerado confiável apenas quando fornece garantias explícitas sobre quatro aspectos da transferência de dados:

  • Garantia de Entrega (No Loss): O protocolo garante que todos os dados enviados pelo transmissor chegarão ao receptor. Se um pacote se perder no caminho, o protocolo detectará essa perda e recuperará o dado via retransmissão.
  • Garantia de Integridade (No Corruption): Os dados não podem ser alterados durante o trânsito. Qualquer erro de bit (0 virando 1) é detectado e corrigido (geralmente via retransmissão).
  • Garantia de Ordenação (In-Order Delivery): Os dados devem ser entregues à aplicação receptora exatamente na mesma sequência em que foram enviados. Como a rede IP pode embaralhar os pacotes, o serviço confiável deve reordená-los no receptor.
  • Garantia de Não Duplicação (No Duplication): Se a rede entregar acidentalmente uma cópia duplicada de um pacote (o que pode acontecer em cenários de retransmissão), o serviço confiável deve descartar a cópia extra, entregando apenas uma instância do dado para a aplicação.

2. Mecanismos de Implementação da Confiabilidade

Para cumprir essas garantias sobre uma rede "best-effort", o serviço confiável utiliza uma série de mecanismos técnicos coordenados, baseados no princípio ARQ (Automatic Repeat reQuest):

A. Números de Sequência (Sequence Numbers)

Cada byte (ou segmento, dependendo da implementação) de dados enviado é numerado sequencialmente. Isso cria uma ordem lógica inquestionável.

  • Função: Permite que o receptor identifique lacunas (pacotes perdidos) e pacotes fora de ordem. Se o receptor tem o byte 1000 e recebe o byte 3000, ele sabe que os bytes entre 1001 e 2999 estão faltando ou a caminho.
  • Remontagem: O receptor usa esses números para montar o fluxo de bytes na ordem correta antes de passá-lo para a aplicação.
  • Detecção de duplicatas: Se chegar um byte com número já recebido, é descartado silenciosamente.
  • Wrap-around: Em TCP, com 32 bits, o número "dá a volta" — RFC 1323 PAWS (Protection Against Wrapped Sequences) usa timestamps para evitar ambiguidade.

B. Confirmação de Recebimento (Acknowledgment - ACK)

O receptor envia feedback de volta para o remetente.

  • ACK Cumulativo (TCP): O receptor envia um número de ACK indicando o próximo byte que espera receber. Por exemplo, enviar ACK 2001 significa "recebi tudo até o byte 2000 corretamente, estou esperando o 2001". Isso confirma implicitamente o recebimento de todos os bytes anteriores.
  • SACK (Selective ACK, RFC 2018): O receptor pode anunciar faixas de bytes recebidas fora de ordem. Ex: SACK blocks: [5000-5999][7000-7999]. O remetente retransmite apenas as lacunas, economizando banda em perdas múltiplas.
  • Delayed ACK (RFC 1122): O receptor pode segurar o ACK por até 200 ms ou até acumular 2 segmentos full-MSS, reduzindo o tráfego de ACK pela metade em fluxos regulares.
  • Piggybacking: Em conexões full-duplex, o receptor envia o ACK junto com dados no sentido contrário, economizando cabeçalho.

C. Temporizadores e Retransmissão (Timers and Retransmission)

O remetente não assume que o dado chegou apenas porque o enviou. Ele inicia um temporizador (timer) para cada pacote não confirmado.

  • Timeout (RTO - Retransmission Timeout): Se o temporizador expirar antes do remetente receber o ACK correspondente, o remetente assume que o pacote foi perdido.
  • Ação: O remetente retransmite (envia novamente) o pacote. Este ciclo continua até que o ACK seja recebido ou a conexão seja abandonada (Linux: tcp_retries2 = 15 ≈ ~924 s).
  • Cálculo do RTO (RFC 6298): SRTT = α·SRTT + (1-α)·RTT (α=7/8); RTTVAR = (1-β)·RTTVAR + β·|RTT-SRTT| (β=3/4); RTO = SRTT + 4·RTTVAR. Born inferior de 1 s (Linux: 200 ms).
  • Algoritmo de Karn/Partridge: Não usar RTT de segmentos retransmitidos no cálculo do SRTT — ambiguidade de qual ACK corresponde a qual envio.
  • Retransmissão Rápida (Fast Retransmit, RFC 5681): Em alguns protocolos (como o TCP), se o remetente receber múltiplos ACKs duplicados (ex: três ACKs seguidos para o mesmo número), ele infere que um pacote foi perdido e o retransmite imediatamente, sem esperar o timeout expirar.
  • RACK (RFC 8985, Linux 4.x+): Mais moderno que o dup-ACK count. Usa o maior número de sequência já confirmado como referência temporal; se um segmento foi enviado antes do momento do RACK e ainda não foi ACKado, ele é considerado perdido.

D. Verificação de Soma (Checksum)

Embora a Camada de Rede tenha um checksum, ele é fraco (cobre apenas o cabeçalho IP). O serviço confiável (TCP) implementa seu próprio checksum que cobre o pseudo-cabeçalho (IP origem, IP destino, protocolo, comprimento TCP), o cabeçalho de transporte e a carga útil (payload).

  • Se o segmento chegar corrompido (erro de bit), o checksum falhará, o segmento será descartado silenciosamente e o remetente eventualmente fará a retransmissão devido à falta de ACK.
  • Limitação: o checksum de complemento de 1 é fraco contra erros intencionais; em ambientes de alto BER, recomenda-se complementar com CRC em camadas inferiores (Ethernet FCS, PPP CRC-32).

3. O Papel dos Buffers

A confiabilidade exige o uso de memória (buffers) tanto no envio quanto na recepção para gerenciar o fluxo não confiável da rede.

  • Buffer de Reenvio (Sending Buffer): O remetente deve manter uma cópia de todos os dados enviados mas ainda não confirmados (ACKed). Se um pacote for perdido, ele precisa dos dados no buffer para retransmitir. Somente após receber o ACK, ele pode liberar esse espaço na memória.
  • Buffer de Recepção (Receiving Buffer): O receptor precisa armazenar dados que chegaram fora de ordem. Se recebeu o pacote 3 antes do 2, ele guarda o 3 no buffer e aguarda o 2 chegar para montar a sequência correta antes de entregar à aplicação. Ele também filtra duplicatas aqui.

Tamanho típico de buffers (Linux):

sysctl net.ipv4.tcp_rmem    # min default max (ex: 4096 87380 6291456)
sysctl net.ipv4.tcp_wmem    # min default max (ex: 4096 16384 4194304)

Ajustar esses valores é crítico em enlaces de alto BDP (banda-delay product), porque a confiabilidade depende de ter buffer suficiente para "segurar" todos os dados em trânsito enquanto aguarda ACKs.

4. Estratégias ARQ

A literatura de redes clássica descreve três protocolos ARQ que exemplificam as abordagens de confiabilidade:

Estratégia Mecanismo Eficiência Usado em
Stop-and-Wait 1 pacote em trânsito; espera ACK antes de próximo Baixíssima (janela=1) RLP, some radio protocols
Go-Back-N Envia N pacotes; perda = retransmite do perdido em diante Média; janela deslizante TCP sem SACK
Selective Repeat Retransmite apenas o pacote perdido Alta; exige buffering TCP com SACK

O TCP moderno, com SACK habilitado (default em Linux desde 2.6), comporta-se praticamente como Selective Repeat.

5. Confiabilidade x Congestionamento

A confiabilidade pura (retransmitir tudo sempre que há perda) pode colapsar a rede se a perda for causada por congestionamento. Por isso, em TCP, o serviço confiável é combinado com o controle de congestionamento, que ajusta a cwnd (janela de congestionamento) em resposta a perdas: a retransmissão continua garantindo entrega, mas o ritmo de envio diminui para não piorar o congestionamento.

A interação é sutil: o controle de erro garante que o que foi enviado chega; o controle de congestionamento decide quanto pode ser enviado por vez. Ambos coexistem no mesmo protocolo, coordenados por sinais comuns (perda, ACKs duplicados, timeout).

6. A Abstração para a Aplicação

O resultado final do serviço confiável é que a aplicação de software (navegador, cliente de e-mail) não precisa se preocupar com a física da rede.

  • Ilusão de Perfeição: Do ponto de vista do programador, é como se houvesse um cabo dedicado e infalível conectando as duas aplicações. O programador escreve dados em um soquete e lê dados dele, sem precisar implementar timers, retransmissões ou verificação de erros. A complexidade de tornar a comunicação confiável é totalmente encapsulada dentro da implementação do protocolo (o kernel do sistema operacional).
  • API simples: connect(), send(), recv(), close() — toda a complexidade está escondida.

Exemplo prático em C (POSIX)

int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr = { .sin_family=AF_INET, .sin_port=htons(80) };
inet_pton(AF_INET, "93.184.216.34", &addr.sin_addr);
connect(sock, (struct sockaddr*)&addr, sizeof(addr));
// A partir daqui, send() e recv() fornecem um canal "perfeito":
ssize_t n = send(sock, "GET / HTTP/1.0\r\n\r\n", 18, 0);
char buf[4096];
while ((n = recv(sock, buf, sizeof(buf), 0)) > 0)
    write(1, buf, n);
close(sock);

A aplicação não sabe — nem precisa saber — quantos pacotes foram perdidos, retransmitidos, reordenados ou duplicados embaixo. Tudo isso é responsabilidade do kernel TCP.

7. Limites da Confiabilidade

Apesar de robusto, o serviço confiável tem limites que a aplicação deve conhecer:

  • Não garante tempestividade: o dado chega, mas pode chegar tarde (depois de várias retransmissões). Aplicações de tempo real sofrem.
  • Não previne head-of-line blocking: se um byte no meio do fluxo é perdido, todos os bytes seguintes ficam retidos até a retransmissão preencher a lacuna.
  • Não corrige erros, apenas detecta: não há FEC (Forward Error Correction) em TCP clássico; a recuperação é sempre por retransmissão. Para enlaces com alto BER (satélite, rádio), às vezes é mais eficiente usar UDP + FEC.
  • Custo de estado: cada conexão consome buffer e TCB no kernel — milhões de conexões idle exigem tuning (tcp_max_tw_buckets, ip_local_port_range, etc.).

Tip

Em Linux, o arquivo /proc/net/snmp exibe contadores TCP (active opens, passive opens, attempt fails, estab resets, retranssegs, in_errs, out_rsts). Já /proc/net/tcp mostra todas as conexões abertas com estado e timer. Comparar retranssegs com outsegs dá a taxa de retransmissão — acima de 1% indica problema de rede.