9.10. TCP – um fluxo fiável de bytes¶
O TCP, Transmission Control Protocol (Protocolo de Controlo de Transmissão), é o outro serviço da camada de transporte sobre IP. Se o UDP pode ser descrito como «envia um pacote e torce para o melhor», o TCP é «abre uma ligação entre dois extremos e trata-a como um canal bidirecional de bytes que o outro lado recebe definitivamente, por ordem e exactamente uma vez». A maior parte do tráfego na internet utiliza-o, e a maior parte do que a câmara faz na rede também.
9.10.1. O que o TCP acrescenta ao IP¶
O TCP faz muito mais do que o UDP. Acrescenta:
Uma ligação. Antes de qualquer dado fluir, os dois extremos trocam um curto handshake para acordar que estão a comunicar. A ligação tem um estado – «aberta», «meio-fechada», «fechada» – que ambos os lados monitorizam.
Entrega fiável. Cada byte que o emissor coloca é confirmado pelo receptor. Tudo o que não for confirmado dentro de um tempo limite é enviado novamente. A aplicação nunca vê um byte perdido; vê um atraso enquanto o protocolo reencaminha.
Entrega por ordem. Os bytes chegam na mesma ordem em que foram enviados. Mesmo que os pacotes cheguem ao receptor fora de ordem, o TCP reordena-os antes de a aplicação os ler.
Controlo de fluxo. Se o receptor for lento, o emissor recebe instrução para abrandar; a ligação adapta-se à taxa do extremo mais lento.
Controlo de congestionamento. Se a rede intermédia começar a descartar pacotes, o emissor recua até as coisas se recuperarem. Isto impede que uma única ligação derrube um elo saturado.
Tudo isto é automático. A API Python que a aplicação utiliza é simplesmente send(bytes) e recv(n); o TCP trata de tudo o resto por baixo.
9.10.2. O handshake¶
Uma ligação TCP abre-se com uma troca de três vias antes de qualquer dado ser permitido:
O handshake de três vias. Assim que ambos os lados tenham confirmado, a ligação está aberta e os dados podem fluir.¶
O cliente envia um pacote SYN (sincronizar) a pedir para abrir. O servidor responde com SYN-ACK (sincronizar + confirmar), aceitando. O cliente envia um ACK final para confirmar. Após esta ida e volta, ambos os lados concordam que a ligação está aberta e sincronizaram os seus contadores para monitorizar quais os bytes que foram enviados e recebidos.
O handshake custa uma latência de ida-e-volta antes do primeiro byte útil passar. Para redes locais é uma milissegundo; para ligações intercontinentais é aproximadamente 100 ms. Este é o principal custo do TCP e a razão pela qual mensagens curtas e pontuais são por vezes mais adequadas usando UDP.
9.10.2.1. O handshake de encerramento¶
As ligações TCP também encerram com uma troca (um FIN de cada lado). Qualquer extremo pode encerrar a sua metade da ligação de forma independente; um estado half-closed onde um lado terminou de enviar mas o outro ainda está a comunicar é legal, embora incomum. A aplicação normalmente apenas chama close() e deixa o protocolo tratar da sequência de encerramento.
9.10.3. O que o TCP não garante¶
Algumas coisas que o TCP por vezes se assume que faz, mas não faz:
Fronteiras de mensagem. A aplicação envia um fluxo de bytes, não um fluxo de mensagens. Duas chamadas
send(b"hello")podem chegar como um únicorecv()deb"hellohello", ou como doisrecv()s de tamanhos variados. Se a aplicação quiser delimitação de mensagens, tem de a adicionar ela própria (uma nova linha, um prefixo de comprimento, o que for). Enviar documentos JSON sobre TCP, por exemplo, requer que cada documento seja separado por uma nova linha ou outro marcador.Encriptação. O TCP transporta os bytes que a aplicação lhe forneceu, em claro, todo o caminho. Se o conteúdo precisar de ser confidencial, a aplicação tem de envolver a ligação em TLS (ver Sockets encriptados e TLS).
Autenticação. O TCP garante que os bytes chegaram intactos. Não diz nada sobre quem os enviou. A autenticação é também uma preocupação de camadas superiores.
Actividade numa ligação silenciosa. Se nenhum dos lados enviar dados durante muito tempo, a ligação está tecnicamente ainda aberta mas não consegue detectar que o outro extremo falhou ou desapareceu. Sondas Keepalive podem ser activadas no socket para corrigir isto quando for relevante.
9.10.4. Quando usar TCP¶
O TCP é a resposta certa para quase qualquer conversa que se enquadre na forma «o cliente abre uma ligação a um servidor, trocam alguns bytes, a ligação fecha quando terminar». Pedidos HTTP e HTTPS, sessões SSH, consultas a bases de dados, transferências de ficheiros, carregamentos de imagens – tudo sobre TCP.
Recorra ao UDP apenas quando a conversa não se enquadra nessa forma: mensagens independentes e auto-contidas onde a perda é aceitável, tráfego multicast, sincronização de tempo, pesquisas de nomes, ou casos extremamente sensíveis à latência onde o custo do handshake é proibitivo.
Com portas, UDP e TCP todos disponíveis, a história da camada de transporte está concluída. A API Python que expõe ambos está na página seguinte: Objetos socket.