Protocolo TCP: mudanças entre as edições
(61 revisões intermediárias pelo mesmo usuário não estão sendo mostradas) | |||
Linha 2: | Linha 2: | ||
O '''protocolo TCP''' (RFC 793), como o [[Protocolo UDP]], também oferece a '''multiplexação/demultiplexação de aplicações''' através das portas e o mecanismo de '''detecção de erros'''. A grande diferença é que o TCP é um protocolo '''orientado a conexão''' e com '''transferência garantida''', onde os dois processos devem acordar entre eles uma abertura de conexão para que os dados possam ser transferidos. Além destas características, o TCP integra ainda um serviço de '''controle de fluxo''', que assegura que nenhum dos lados da comunicação envie pacotes rápido demais, pois uma aplicação em um lado pode não conseguir processar a informação na velocidade que está recebendo, e um serviço de '''controle de congestionamento''' ajuda a prevenir congestionamentos na rede. | O '''protocolo TCP''' (RFC 793), como o [[Protocolo UDP]], também oferece a '''multiplexação/demultiplexação de aplicações''' através das portas e o mecanismo de '''detecção de erros'''. A grande diferença é que o TCP é um protocolo '''orientado a conexão''' e com '''transferência garantida''', onde os dois processos devem acordar entre eles uma abertura de conexão para que os dados possam ser transferidos. Além destas características, o TCP integra ainda um serviço de '''controle de fluxo''', que assegura que nenhum dos lados da comunicação envie pacotes rápido demais, pois uma aplicação em um lado pode não conseguir processar a informação na velocidade que está recebendo, e um serviço de '''controle de congestionamento''' ajuda a prevenir congestionamentos na rede. | ||
==Formato do segmento TCP== | |||
O cabeçalho do segmento TCP, além dos '''números de porta origem e destino''' e ''''' | O cabeçalho do segmento TCP, além dos '''números de porta origem e destino''' e '''''checksum''''', que também existem no UDP, há outros campos com informações necessárias a implementação do serviço de transferência garantida, controle de fluxo e controle de congestionamento. Veja figura (RFC 793): | ||
0 1 2 3 | 0 1 2 3 | ||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||
Linha 27: | Linha 27: | ||
*'''Número de seqüência''' e '''reconhecimento''', utilizado para o emissor e receptor implementarem o serviço de transferência garantida (''Sequence Number'' e ''Acknowledgment Number''). | *'''Número de seqüência''' e '''reconhecimento''', utilizado para o emissor e receptor implementarem o serviço de transferência garantida (''Sequence Number'' e ''Acknowledgment Number''). | ||
*Tamanho da '''janela do receptor''', usado para o controle de fluxo, e indica o número de bytes que o receptor é capaz de receber (''Window''). | *Tamanho da '''janela do receptor''', usado para o controle de fluxo, e indica o número de bytes que o receptor é capaz de receber (''Window''). | ||
*Seis bits de ''flags'': | *Seis bits de ''flags'': | ||
**'''Ack''' é usado para indicar que o campo de reconhecimento é válido; | |||
** '''Syn''', '''Fin''' e '''Rst''' são usados para o controle de abertura e encerramento de conexão; | |||
**'''Psh''' indica ao receptor que o segmento tem dados prontos para passar a camada superior; | |||
**'''Urg''' indica a presença de dados urgentes no segmento, situados entre o primeiro byte e o byte apontado pelo campo ''Urgent Pointer'' (este ''flag'' praticamente não é mais utilizado). | |||
*'''Tamanho do cabeçalho''' (''Data Offset''), especifica o tamanho da cabeçalho em linhas de 32 bits, que pode variar em funções do campo de opções; tipicamente o cabeçalho contém as 5 primeiras linhas, totalizando 20 bytes. | *'''Tamanho do cabeçalho''' (''Data Offset''), especifica o tamanho da cabeçalho em linhas de 32 bits, que pode variar em funções do campo de opções; tipicamente o cabeçalho contém as 5 primeiras linhas, totalizando 20 bytes. | ||
*O '''''checksum''''' é usado para detecção de erros. | *O '''''checksum''''' é usado para detecção de erros. | ||
*O '''campo de opções''' (''Options'') é usado quando o emissor e receptor precisam negociar algum parâmetro, como por exemplo na abertura de conexão para acordar o tamanho máximo de segmento (MSS). | *O '''campo de opções''' (''Options'') é usado quando o emissor e receptor precisam negociar algum parâmetro, como por exemplo na abertura de conexão para acordar o tamanho máximo de segmento (MSS). O ''Padding'' é utilizado para completar o campo opções (se necessário). | ||
===Tamanho do segmento TCP=== | |||
O campo de '''dados da aplicação''' (''data'') do segmento TCP, contém um fragmento ou pedaço dos dados da aplicação, cujo tamanho máximo é chamado de '''Tamanho Máximo do Segmento''' ou '''MSS''' (''Maximum Segment Size''), não considerando o cabeçalho. | O campo de '''dados da aplicação''' (''data'') do segmento TCP, contém um fragmento ou pedaço dos dados da aplicação, cujo tamanho máximo é chamado de '''Tamanho Máximo do Segmento''' ou '''MSS''' (''Maximum Segment Size''), não considerando o cabeçalho. | ||
Linha 46: | Linha 49: | ||
[[Arquivo:MTU.png]] | [[Arquivo:MTU.png]] | ||
==Números de sequência e reconhecimento TCP== | |||
Dois campos importantes do segmento TCP são os '''números de | Dois campos importantes do segmento TCP são os '''números de sequência''' e '''reconhecimento''', os quais implementam o controle da '''transferência de dados confiável'''. | ||
Como vimos, os '''dados das aplicações''' são transportados pelos segmentos TCP. Caso as mensagens sejam maiores que o valor de '''MSS''', '''Tamanho Máximo do Segmento''', as mesmas são '''fragmentadas''' para poderem ser acomodadas na parte de dados do segmento. Por exemplo, um arquivo GIF de 500.000 bytes trocado pelo HTTP será fragmentado em vários pedaços para ser transmitido pelo TCP. Os números de sequência servem, portanto, para que o lado receptor TCP possa reordenar corretamente os dados recebidos. | Como vimos, os '''dados das aplicações''' são transportados pelos segmentos TCP. Caso as mensagens sejam maiores que o valor de '''MSS''', '''Tamanho Máximo do Segmento''', as mesmas são '''fragmentadas''' para poderem ser acomodadas na parte de dados do segmento. Por exemplo, um arquivo GIF de 500.000 bytes trocado pelo HTTP será fragmentado em vários pedaços para ser transmitido pelo TCP. Os números de sequência servem, portanto, para que o lado receptor TCP possa reordenar corretamente os dados recebidos. | ||
Linha 53: | Linha 56: | ||
Os números de sequência correspondem a quantidade de bytes que o TCP está transmitindo. Por exemplo, suponha que o bloco total de dados que será transmitido tenha 500.000 bytes, que o valor de MSS é de 1.000 bytes. Suponha que o primeiro byte dos dados é numerado como zero. Para transmitir esta quantidade de bytes o TCP formará 500 segmentos. Ao primeiro segmento atribui-se o número de sequência zero, ao segundo 1000, ao terceiro 2000 e assim por diante <ref name="KUROSE">KUROSE, J.F; ROSS K. W. Redes de Computadores e a Internet: Uma abordagem ''top-down'', São Paulo: Pearson, 2010.</ref>. | Os números de sequência correspondem a quantidade de bytes que o TCP está transmitindo. Por exemplo, suponha que o bloco total de dados que será transmitido tenha 500.000 bytes, que o valor de MSS é de 1.000 bytes. Suponha que o primeiro byte dos dados é numerado como zero. Para transmitir esta quantidade de bytes o TCP formará 500 segmentos. Ao primeiro segmento atribui-se o número de sequência zero, ao segundo 1000, ao terceiro 2000 e assim por diante <ref name="KUROSE">KUROSE, J.F; ROSS K. W. Redes de Computadores e a Internet: Uma abordagem ''top-down'', São Paulo: Pearson, 2010.</ref>. | ||
[[Arquivo:NumeroSequencia.png]] | [[Arquivo:NumeroSequencia.png|700px]] | ||
O '''número de reconhecimento''' que o host A coloca no seu segmento é o '''número de sequência''' do próximo byte que o host A espera receber do host B. Por exemplo, suponha que o host A recebeu todos os bytes numerados de 0 a 535 de B e que está prestes a enviar um segmento a B. Neste caso, o host A coloca como número de reconhecimento 536, o que vai indicar a B que o mesmo recebeu todos os bytes até este número <ref name="KUROSE" />. | O '''número de reconhecimento''' que o host A coloca no seu segmento é o '''número de sequência''' do próximo byte que o host A espera receber do host B. Por exemplo, suponha que o host A recebeu todos os bytes numerados de 0 a 535 de B e que está prestes a enviar um segmento a B. Neste caso, o host A coloca como número de reconhecimento 536, o que vai indicar a B que o mesmo recebeu todos os bytes até este número <ref name="KUROSE" />. | ||
[[Arquivo:SequenciaTCP1.png]] | |||
Em outro exemplo, suponha que o host A recebeu todos os bytes numerados de 0 a 535 de B e em seguida recebeu de B um segmento contendo bytes de 900 a 1000. Note que A não recebeu os bytes que vão de 536 a 899. Como A ainda está esperando bytes a partir de 536, ele reenvia a B um segmento com número de reconhecimento 536. Continuando este exemplo, suponha agora que A receba o segmento que faltava, com os bytes que vão de 536 a 899. Neste caso, como ele já recebeu inclusive os dados contendo os bytes de 900 a 1000, ele envia um reconhecimento com número 1001. Isto é chamado de '''reconhecimento cumulativo''', que indica que recebeu todos os bytes até este número <ref name="KUROSE" />. | Em outro exemplo, suponha que o host A recebeu todos os bytes numerados de 0 a 535 de B e em seguida recebeu de B um segmento contendo bytes de 900 a 1000. Note que A não recebeu os bytes que vão de 536 a 899. Como A ainda está esperando bytes a partir de 536, ele reenvia a B um segmento com número de reconhecimento 536. Continuando este exemplo, suponha agora que A receba o segmento que faltava, com os bytes que vão de 536 a 899. Neste caso, como ele já recebeu inclusive os dados contendo os bytes de 900 a 1000, ele envia um reconhecimento com número 1001. Isto é chamado de '''reconhecimento cumulativo''', que indica que recebeu todos os bytes até este número <ref name="KUROSE" />. | ||
[[Arquivo:SequenciaTCP2.png]] | |||
==Conexão TCP== | |||
Para trocarem segmentos de dados utilizando o TCP o emissor e o receptor devem estabelecer uma '''conexão TCP''' através da troca de pacotes de controle entre si. Isto é chamado de procedimento de '''estabelecimento de conexão''' (''handshaking''), onde se estabelecem os parâmetros para a comunicação. Uma vez concluído o ''handshaking'' a conexão é dita estabelecida e os dois sistemas terminais podem trocar dados. | Para trocarem segmentos de dados utilizando o TCP o emissor e o receptor devem estabelecer uma '''conexão TCP''' através da troca de pacotes de controle entre si. Isto é chamado de procedimento de '''estabelecimento de conexão''' (''handshaking''), onde se estabelecem os parâmetros para a comunicação. Uma vez concluído o ''handshaking'' a conexão é dita estabelecida e os dois sistemas terminais podem trocar dados. | ||
Linha 65: | Linha 72: | ||
O cliente solicita a '''estabelecimento de conexão''' em uma '''porta bem conhecida do servidor''' (por exemplo, porta 80 de um servidor Web) e informa a '''porta origem''' para receber as respostas, além de ajustar outros parâmetros para implementar a '''transferência garantida'''. | O cliente solicita a '''estabelecimento de conexão''' em uma '''porta bem conhecida do servidor''' (por exemplo, porta 80 de um servidor Web) e informa a '''porta origem''' para receber as respostas, além de ajustar outros parâmetros para implementar a '''transferência garantida'''. | ||
===Estabelecimento de conexão TCP=== | |||
Na fase de estabelecimento de conexão, são inicializadas as variáveis do protocolo TCP, como os '''números de sequência''' inicial e o tamanho de ''buffers''. O processo cliente é o que inicia o estabelecimento da conexão, sendo o servidor contatado pelo cliente. | Na fase de estabelecimento de conexão, são inicializadas as variáveis do protocolo TCP, como os '''números de sequência''' inicial e o tamanho de ''buffers''. O processo cliente é o que inicia o estabelecimento da conexão, sendo o servidor contatado pelo cliente. | ||
Linha 76: | Linha 83: | ||
#Uma vez recebido o reconhecimento da conexão pelo servidor, o cliente '''confirma a conexão''' com um segmento chamado '''ACK''' (''flag'' Syn agora em 0 e '''''flag'' Ack''' setado em 1 indicando um reconhecimento válido) e também aloca buffers e inicializa variáveis da conexão (Seq=X+1, Ack=Y+1). | #Uma vez recebido o reconhecimento da conexão pelo servidor, o cliente '''confirma a conexão''' com um segmento chamado '''ACK''' (''flag'' Syn agora em 0 e '''''flag'' Ack''' setado em 1 indicando um reconhecimento válido) e também aloca buffers e inicializa variáveis da conexão (Seq=X+1, Ack=Y+1). | ||
===Recusa de conexão=== | |||
No caso de uma '''recusa de conexão''', por exemplo quando um cliente solicita uma conexão numa porta inativa, o servidor contatado envia um segmento de controle chamado '''RST''' (''reset'') (com o '''''flag'' Rst''' setado em 1), conforme ilustra a figura <ref name="STEVENS" />: | No caso de uma '''recusa de conexão''', por exemplo quando um cliente solicita uma conexão numa porta inativa, o servidor contatado envia um segmento de controle chamado '''RST''' (''reset'') (com o '''''flag'' Rst''' setado em 1), conforme ilustra a figura <ref name="STEVENS" />: | ||
Linha 82: | Linha 89: | ||
[[Arquivo:RecusaConexao.png]] | [[Arquivo:RecusaConexao.png]] | ||
===Encerramento de conexão=== | |||
Para o '''enceramento da conexão''' quatro segmentos são trocados. Quem inicia a desconexão envia de um segmento especial, chamado '''FIN''' (com ''flag Fin'' setado em 1). Quem recebe o segmento, primeiro reconhece a solicitação de fim da conexão e depois envia ele também um segmento '''FIN''' (Estas duas mensagens podem estar concatenadas em uma única mensagem '''FIN-ACK'''). O encerramento definitivo da conexão se dá quando o que iniciou a desconexão recebe e reconhece o segundo segmento FIN, conforme ilustra a figura <ref name="STEVENS" />. | Para o '''enceramento da conexão''' quatro segmentos são trocados. Quem inicia a desconexão envia de um segmento especial, chamado '''FIN''' (com ''flag Fin'' setado em 1). Quem recebe o segmento, primeiro reconhece a solicitação de fim da conexão e depois envia ele também um segmento '''FIN''' (Estas duas mensagens podem estar concatenadas em uma única mensagem '''FIN-ACK'''). O encerramento definitivo da conexão se dá quando o que iniciou a desconexão recebe e reconhece o segundo segmento FIN, conforme ilustra a figura <ref name="STEVENS" />. | ||
[[Arquivo:EncerramentoConexao.png]] | [[Arquivo:EncerramentoConexao.png]] | ||
===''Flag'' Psh === | |||
O TCP é visto pela '''camada aplicação''' como uma simples '''porta''' ('''''socket''''') por onde as informações são enviadas ou recebidas. | |||
A medida que a aplicação emissora passa dados ao TCP os mesmos vão sendo alocados em um '''''buffer'' de envio'''. O TCP, por sua vez, vai processando as informações presentes no ''buffer'', procurando montar os segmentos para envio de acordo com o valor do MSS. | |||
No lado do receptor, a medida que os segmentos vão chegando, são alocados em um '''''buffer'' de recepção''' e ficam disponíveis para processamento pela aplicação remota. | |||
No caso de '''aplicações interativas''', que exigem resposta imediata do lado do receptor, a aplicação que envia deve informar ao TCP para entregar imediatamente os dados para aplicação receptora. Isto é realizado através do '''''flag'' Psh'''. <ref>STRETCH, J. TCP Flags: PSH and URG: http://packetlife.net/blog/2011/mar/2/tcp-flags-psh-and-urg/</ref>. | |||
;Exemplo de uso do '''''flag'' Psh''': Quando um '''cliente HTTP''' solicita uma página Web através do '''comando GET''' a solicitação deve ser imediatamente passada ao servidor Web. Assim o TCP monta o segmento com a solicitação e o '''''flag'' Psh''' setado. Da mesma forma, quando o '''servidor HTTP''' envia a página Web solicitada pelo cliente, o '''segmento com os últimos bytes''' da solicitação vem com o '''''flag'' Psh''' setado. | |||
==Controle de Fluxo TCP== | |||
O '''controle de fluxo''' no TCP visa evitar que um emissor não '''afogue''' um receptor, enviando mais dados mais rápido do que ele possa processar. | |||
Quando uma conexão TCP recebe bytes que estão corretos e em sequência ela os armazena em um '''''buffer'' de recepção''' para que a aplicação possa processá-los. Entretanto, a aplicação pode não ler estes dados imediatamente, já que é um processo independente. Assim, pode ocorrer um estouro da capacidade do ''buffer''. Desta forma, o mecanismo de '''controle de fluxo''' implementa um tipo de casamento de velocidades entre o emissor e o receptor. | |||
O controle de fluxo é implementado por meio de uma variável, chamada '''janela do receptor''' (''Receive Window''), que mantém o valor atual da capacidade de armazenamento do '''''buffer'' de recepção'''. Esta janela limita a quantidade de bytes que pode ser enviada antes de esperar por um reconhecimento. | |||
A variável '''janela do receptor''' faz parte do cabeçalho TCP (''Window''), e seu tamanho é dinâmico, podendo variar durante uma conexão. A cada troca de segmentos o receptor informa o tamanho atual da janela em Bytes. | |||
Como a conexão é ''full-duplex'', cada um dos receptores mantém a informação sobre sua janela de recepção. | |||
A figura a seguir o mecanismo de controle de fluxo. Novos dados chegando do emissor ocupam o espaço livre do buffer. Dados consumidos pela aplicação liberam espaço do buffer. | |||
[[Arquivo:ControleFluxo.png]] | |||
==Temporização no TCP== | |||
A cada segmento enviado pelo TCP ele inicializa um '''temporizador''' visando aguardar um reconhecimento em um tempo limite. Em caso de '''estouro do temporizador''' ('''''timeout''''') o TCP retransmite o segmento. | |||
O valor do '''temporizador''' deve ser '''maior''' que o '''tempo de ida e volta''' dos pacotes. Contudo, não pode ser muito pequeno, pois pode gerar estouro desnecessário do temporizador, nem muito longo, pois aumenta o tempo de reação a possíveis erros. | |||
Para definir o valor do temporizador o TCP faz uma '''estimativa''' dinâmica do tempo de ida e volta dos pacotes, chamado '''RTT''' (''roud trip time''). A partir desta estimativa, calcula o valor médio e desvio, e aplica uma margem de segurança para definir o valor do temporizador. | |||
A figura abaixo ilustra o processo de estimativa do tempo de ida e volta (RTT) dos pacotes no TCP . | |||
[[Arquivo: TemporizacaoTCP.png|600px]] Fonte: <ref name="KUROSE" /> | |||
==Controle de Congestionamento TCP== | |||
O controle de congestionamento visa minimizar o congestionamento no núcleo da rede. | |||
O TCP implementa um '''mecanismo de controle de congestionamento fim a fim''' inferido a partir da observação dos '''pacotes perdidos''' ou recebidos com '''atraso'''. A ideia é relativamente simples. Caso o TCP detecte atrasos ou perda de pacotes ele supõe que há congestionamento da rede. A partir dai o TCP diminui o fluxo de pacotes enviado, visando colaborar com a diminuição do possível congestionamento no núcleo da rede. | |||
Os '''atrasos''' ocorrem quando há atrasos significativos em filas nos roteadores. | |||
A '''perda de pacotes''' ocorre quando estoura a capacidade de armazenamento nos roteadores devido ao congestionamento e os novos pacotes que chegam são descartados (''dropped''). | |||
O TCP controla sua '''taxa de transmissão''', ou '''vazão''', limitando o número de segmentos transmitidos e ainda não reconhecidos. | |||
===Controle de fluxo X Controle de congestionamento=== | |||
Como vimos anteriormente, o '''controle de fluxo''' no TCP depende do tamanho da '''janela do receptor''', a qual o receptor informa ao emissor a cada troca de pacotes, usando o campo ''Window'' do cabeçalho TCP. | |||
No caso do '''controle de congestionamento''', o emissor usa uma variável adicional chamada '''janela de congestionamento''', a qual limita a transmissão em função do congestionamento percebido na rede. | |||
A qualquer tempo, a quantidade de dados enviados e não reconhecidos dentro de uma conexão TCP não deve exceder o mínimo entre a '''janela de congestionamento''' e a '''janela do receptor'''. | |||
Janela máxima = MIN(Janela de congestionamento, Janela do receptor) | |||
===Funcionamento do controle de congestionamento TCP=== | |||
A ideia do '''controle de congestionamento''' é permitir que o TCP transmita o mais rápido possível, desde que não perda segmentos. Para isto, a conexão TCP começa com uma '''janela de congestionamento''' de tamanho pequeno, visando sondar a existência de banda, e vai aumentando o tamanho da janela até que ocorra uma perda. Quando isto acontece, o TCP reduz o tamanho da janela para um nível seguro, e volta a aumentá-la, sondando novamente a existência de banda. | |||
====Partida Lenta==== | |||
Assim que a '''conexão TCP''' é estabelecida, a '''aplicação''' remetente escreve bytes no '''''buffer'' de envio''' do TCP emissor. O TCP agrupa os bytes em '''segmentos''' de tamanho '''MSS''' e envia para a camada rede para transmissão. | |||
Inicialmente a '''janela de congestionamento''' é igual a '''um MSS'''. Isto significa que o TCP envia um segmento e espera por um reconhecimento. Se este segmento foi reconhecido antes do estouro do temporizador, o TCP '''dobra''' o tamanho da janela de congestionamento, passando a enviar dois segmentos. Se receber reconhecimentos novamente, volta a dobrar o tamanho da janela para quatro, e assim por diante. | |||
[[Arquivo:PartidaLenta.png]] | |||
O TCP continua este procedimento enquanto: | |||
*a janela de congestionamento estiver abaixo de um '''valor de limiar'''; | |||
*os reconhecimentos chegarem antes do estouro do '''temporizador'''. | |||
Esta fase do controle de congestionamento é chamada de '''partida lenta''', na qual a janela inicia com o valor de MSS e aumenta de forma '''exponencial'''. | |||
====Prevenção de Congestionamento==== | |||
A fase de '''partida lenta''' termina quando o tamanho da janela atinge o '''valor de limiar''' (''threshold''). A partir deste momento a janela continua a crescer '''linearmente''', um MSS para cada RTT. Esta fase é chamada de '''prevenção de congestionamento'''. | |||
Se houver um '''estouro de temporização''', o '''valor do limiar''' é ajustado para a metade do valor corrente da janela, e a janela é ajustada para um MSS, reiniciando o processo de '''partida lenta'''. | |||
[[Arquivo:JanelaCongestionamento.png|400px]] Fonte: <ref name="KUROSE" /> | |||
O '''estouro da temporização''' é um '''evento drástico''', pois indica que não estão chegando reconhecimentos vindos do lado do receptor. Isto justifica reiniciar o processo de '''partida lenta''', diminuindo o tamanho da janela de congestionamento para um MSS. | |||
====Retransmissão rápida e AIMD==== | |||
Caso o TCP receba '''três reconhecimentos duplicados''' antes de um estouro de temporizador, o mesmo saberá que o outro lado deve ter recebido pacotes fora de ordem, o que sugere que o pacote anterior tenha sido perdido ou está atrasado. | |||
[[Arquivo:AckDuplicados.png]] | |||
Neste caso, o emissor '''retransmite''' imediatamente o pacote solicitado, o que é chamado '''retransmissão rápida'''. Além disto, o TCP ele reduz o tamanho da '''janela de congestionamento''' para a metade de seu valor corrente e volta a crescer linearmente. Este algoritmo é chamado de '''aumento aditivo, dimuinuição multiplicativa''' ('''AIMD''' - ''additive-increase, multiplicative-decrease''). | |||
[[Arquivo:AIMD.jpg|400px]] Fonte: <ref>http://alpha.tmit.bme.hu/meresek/lantcp_eng.htm#tcpretrasmission</ref>. | |||
A filosofia do AIMD é que '''três reconhecimentos duplicados''' indica que a rede é capaz de entregar alguns segmentos. Entretanto, um '''estouro de temporizador''' antes de três reconhecimentos duplicados é mais alarmante e justifica reiniciar a '''partida lenta'''. | |||
Ao longo do tempo de vida de uma conexão TCP, a variação da '''janela de congestionamento''' segue um padrão de continuidade aumentando e diminuindo, como mostrado no formato '''dente de serra''' do '''AIMD'''. | |||
==Referências== | ==Referências== |
Edição atual tal como às 10h37min de 29 de maio de 2015
Protocolo TCP
O protocolo TCP (RFC 793), como o Protocolo UDP, também oferece a multiplexação/demultiplexação de aplicações através das portas e o mecanismo de detecção de erros. A grande diferença é que o TCP é um protocolo orientado a conexão e com transferência garantida, onde os dois processos devem acordar entre eles uma abertura de conexão para que os dados possam ser transferidos. Além destas características, o TCP integra ainda um serviço de controle de fluxo, que assegura que nenhum dos lados da comunicação envie pacotes rápido demais, pois uma aplicação em um lado pode não conseguir processar a informação na velocidade que está recebendo, e um serviço de controle de congestionamento ajuda a prevenir congestionamentos na rede.
Formato do segmento TCP
O cabeçalho do segmento TCP, além dos números de porta origem e destino e checksum, que também existem no UDP, há outros campos com informações necessárias a implementação do serviço de transferência garantida, controle de fluxo e controle de congestionamento. Veja figura (RFC 793):
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgment Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | |U|A|P|R|S|F| | | Offset| Reserved |R|C|S|S|Y|I| Window | | | |G|K|H|T|N|N| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | Urgent Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Os campos fundamentais do segmento TCP são os seguintes:
- Porta origem e porta destino (Source Port e Destination Port);
- Número de seqüência e reconhecimento, utilizado para o emissor e receptor implementarem o serviço de transferência garantida (Sequence Number e Acknowledgment Number).
- Tamanho da janela do receptor, usado para o controle de fluxo, e indica o número de bytes que o receptor é capaz de receber (Window).
- Seis bits de flags:
- Ack é usado para indicar que o campo de reconhecimento é válido;
- Syn, Fin e Rst são usados para o controle de abertura e encerramento de conexão;
- Psh indica ao receptor que o segmento tem dados prontos para passar a camada superior;
- Urg indica a presença de dados urgentes no segmento, situados entre o primeiro byte e o byte apontado pelo campo Urgent Pointer (este flag praticamente não é mais utilizado).
- Tamanho do cabeçalho (Data Offset), especifica o tamanho da cabeçalho em linhas de 32 bits, que pode variar em funções do campo de opções; tipicamente o cabeçalho contém as 5 primeiras linhas, totalizando 20 bytes.
- O checksum é usado para detecção de erros.
- O campo de opções (Options) é usado quando o emissor e receptor precisam negociar algum parâmetro, como por exemplo na abertura de conexão para acordar o tamanho máximo de segmento (MSS). O Padding é utilizado para completar o campo opções (se necessário).
Tamanho do segmento TCP
O campo de dados da aplicação (data) do segmento TCP, contém um fragmento ou pedaço dos dados da aplicação, cujo tamanho máximo é chamado de Tamanho Máximo do Segmento ou MSS (Maximum Segment Size), não considerando o cabeçalho.
O valor do MSS é acertado entre o emissor e o receptor na abertura de conexão TCP, utilizando o campo opções do cabeçalho TCP.
Em geral o valor de MSS é escolhido para evitar a fragmentação do datagrama IP na camada inferior. Ou seja:
MSS + headers ≤ MTU
O valor MTU (Maximum Tranfer Unit) é a Unidade Máxima de Transferência da camada enlace. Um valor típico para MTU nas redes locais Ethernet é 1500 Bytes. Considerando que tanto o TCP quanto o IP tenham cabeçalho padrão de 20 Bytes, um valor comum para MSS é 1460 Bytes.
Números de sequência e reconhecimento TCP
Dois campos importantes do segmento TCP são os números de sequência e reconhecimento, os quais implementam o controle da transferência de dados confiável.
Como vimos, os dados das aplicações são transportados pelos segmentos TCP. Caso as mensagens sejam maiores que o valor de MSS, Tamanho Máximo do Segmento, as mesmas são fragmentadas para poderem ser acomodadas na parte de dados do segmento. Por exemplo, um arquivo GIF de 500.000 bytes trocado pelo HTTP será fragmentado em vários pedaços para ser transmitido pelo TCP. Os números de sequência servem, portanto, para que o lado receptor TCP possa reordenar corretamente os dados recebidos.
Os números de sequência correspondem a quantidade de bytes que o TCP está transmitindo. Por exemplo, suponha que o bloco total de dados que será transmitido tenha 500.000 bytes, que o valor de MSS é de 1.000 bytes. Suponha que o primeiro byte dos dados é numerado como zero. Para transmitir esta quantidade de bytes o TCP formará 500 segmentos. Ao primeiro segmento atribui-se o número de sequência zero, ao segundo 1000, ao terceiro 2000 e assim por diante [1].
O número de reconhecimento que o host A coloca no seu segmento é o número de sequência do próximo byte que o host A espera receber do host B. Por exemplo, suponha que o host A recebeu todos os bytes numerados de 0 a 535 de B e que está prestes a enviar um segmento a B. Neste caso, o host A coloca como número de reconhecimento 536, o que vai indicar a B que o mesmo recebeu todos os bytes até este número [1].
Em outro exemplo, suponha que o host A recebeu todos os bytes numerados de 0 a 535 de B e em seguida recebeu de B um segmento contendo bytes de 900 a 1000. Note que A não recebeu os bytes que vão de 536 a 899. Como A ainda está esperando bytes a partir de 536, ele reenvia a B um segmento com número de reconhecimento 536. Continuando este exemplo, suponha agora que A receba o segmento que faltava, com os bytes que vão de 536 a 899. Neste caso, como ele já recebeu inclusive os dados contendo os bytes de 900 a 1000, ele envia um reconhecimento com número 1001. Isto é chamado de reconhecimento cumulativo, que indica que recebeu todos os bytes até este número [1].
Conexão TCP
Para trocarem segmentos de dados utilizando o TCP o emissor e o receptor devem estabelecer uma conexão TCP através da troca de pacotes de controle entre si. Isto é chamado de procedimento de estabelecimento de conexão (handshaking), onde se estabelecem os parâmetros para a comunicação. Uma vez concluído o handshaking a conexão é dita estabelecida e os dois sistemas terminais podem trocar dados.
O cliente solicita a estabelecimento de conexão em uma porta bem conhecida do servidor (por exemplo, porta 80 de um servidor Web) e informa a porta origem para receber as respostas, além de ajustar outros parâmetros para implementar a transferência garantida.
Estabelecimento de conexão TCP
Na fase de estabelecimento de conexão, são inicializadas as variáveis do protocolo TCP, como os números de sequência inicial e o tamanho de buffers. O processo cliente é o que inicia o estabelecimento da conexão, sendo o servidor contatado pelo cliente.
O estabelecimento da conexão se dá em três passos, conforme mostrado na figura [2]:
- O lado cliente do TCP envia um segmento de sincronização, chamado SYN (com o flag Syn setado em 1), ao lado servidor do TCP, especificando um número de sequência inicial escolhido aleatóriamente (Seq=X).
- O servidor recebe o SYN, aloca buffers e inicializa variáveis, e envia uma mensagem de reconhecimento da conexão, chamada SYNACK (com o flags Syn e Ack setados em 1), onde reconhece o pedido de conexão e especifica seu número de sequência inicial (Seq=Y, Ack=X+1).
- Uma vez recebido o reconhecimento da conexão pelo servidor, o cliente confirma a conexão com um segmento chamado ACK (flag Syn agora em 0 e flag Ack setado em 1 indicando um reconhecimento válido) e também aloca buffers e inicializa variáveis da conexão (Seq=X+1, Ack=Y+1).
Recusa de conexão
No caso de uma recusa de conexão, por exemplo quando um cliente solicita uma conexão numa porta inativa, o servidor contatado envia um segmento de controle chamado RST (reset) (com o flag Rst setado em 1), conforme ilustra a figura [2]:
Encerramento de conexão
Para o enceramento da conexão quatro segmentos são trocados. Quem inicia a desconexão envia de um segmento especial, chamado FIN (com flag Fin setado em 1). Quem recebe o segmento, primeiro reconhece a solicitação de fim da conexão e depois envia ele também um segmento FIN (Estas duas mensagens podem estar concatenadas em uma única mensagem FIN-ACK). O encerramento definitivo da conexão se dá quando o que iniciou a desconexão recebe e reconhece o segundo segmento FIN, conforme ilustra a figura [2].
Flag Psh
O TCP é visto pela camada aplicação como uma simples porta (socket) por onde as informações são enviadas ou recebidas.
A medida que a aplicação emissora passa dados ao TCP os mesmos vão sendo alocados em um buffer de envio. O TCP, por sua vez, vai processando as informações presentes no buffer, procurando montar os segmentos para envio de acordo com o valor do MSS.
No lado do receptor, a medida que os segmentos vão chegando, são alocados em um buffer de recepção e ficam disponíveis para processamento pela aplicação remota.
No caso de aplicações interativas, que exigem resposta imediata do lado do receptor, a aplicação que envia deve informar ao TCP para entregar imediatamente os dados para aplicação receptora. Isto é realizado através do flag Psh. [3].
- Exemplo de uso do flag Psh
- Quando um cliente HTTP solicita uma página Web através do comando GET a solicitação deve ser imediatamente passada ao servidor Web. Assim o TCP monta o segmento com a solicitação e o flag Psh setado. Da mesma forma, quando o servidor HTTP envia a página Web solicitada pelo cliente, o segmento com os últimos bytes da solicitação vem com o flag Psh setado.
Controle de Fluxo TCP
O controle de fluxo no TCP visa evitar que um emissor não afogue um receptor, enviando mais dados mais rápido do que ele possa processar.
Quando uma conexão TCP recebe bytes que estão corretos e em sequência ela os armazena em um buffer de recepção para que a aplicação possa processá-los. Entretanto, a aplicação pode não ler estes dados imediatamente, já que é um processo independente. Assim, pode ocorrer um estouro da capacidade do buffer. Desta forma, o mecanismo de controle de fluxo implementa um tipo de casamento de velocidades entre o emissor e o receptor.
O controle de fluxo é implementado por meio de uma variável, chamada janela do receptor (Receive Window), que mantém o valor atual da capacidade de armazenamento do buffer de recepção. Esta janela limita a quantidade de bytes que pode ser enviada antes de esperar por um reconhecimento.
A variável janela do receptor faz parte do cabeçalho TCP (Window), e seu tamanho é dinâmico, podendo variar durante uma conexão. A cada troca de segmentos o receptor informa o tamanho atual da janela em Bytes.
Como a conexão é full-duplex, cada um dos receptores mantém a informação sobre sua janela de recepção.
A figura a seguir o mecanismo de controle de fluxo. Novos dados chegando do emissor ocupam o espaço livre do buffer. Dados consumidos pela aplicação liberam espaço do buffer.
Temporização no TCP
A cada segmento enviado pelo TCP ele inicializa um temporizador visando aguardar um reconhecimento em um tempo limite. Em caso de estouro do temporizador (timeout) o TCP retransmite o segmento.
O valor do temporizador deve ser maior que o tempo de ida e volta dos pacotes. Contudo, não pode ser muito pequeno, pois pode gerar estouro desnecessário do temporizador, nem muito longo, pois aumenta o tempo de reação a possíveis erros.
Para definir o valor do temporizador o TCP faz uma estimativa dinâmica do tempo de ida e volta dos pacotes, chamado RTT (roud trip time). A partir desta estimativa, calcula o valor médio e desvio, e aplica uma margem de segurança para definir o valor do temporizador.
A figura abaixo ilustra o processo de estimativa do tempo de ida e volta (RTT) dos pacotes no TCP .
Fonte: [1]
Controle de Congestionamento TCP
O controle de congestionamento visa minimizar o congestionamento no núcleo da rede.
O TCP implementa um mecanismo de controle de congestionamento fim a fim inferido a partir da observação dos pacotes perdidos ou recebidos com atraso. A ideia é relativamente simples. Caso o TCP detecte atrasos ou perda de pacotes ele supõe que há congestionamento da rede. A partir dai o TCP diminui o fluxo de pacotes enviado, visando colaborar com a diminuição do possível congestionamento no núcleo da rede.
Os atrasos ocorrem quando há atrasos significativos em filas nos roteadores.
A perda de pacotes ocorre quando estoura a capacidade de armazenamento nos roteadores devido ao congestionamento e os novos pacotes que chegam são descartados (dropped).
O TCP controla sua taxa de transmissão, ou vazão, limitando o número de segmentos transmitidos e ainda não reconhecidos.
Controle de fluxo X Controle de congestionamento
Como vimos anteriormente, o controle de fluxo no TCP depende do tamanho da janela do receptor, a qual o receptor informa ao emissor a cada troca de pacotes, usando o campo Window do cabeçalho TCP.
No caso do controle de congestionamento, o emissor usa uma variável adicional chamada janela de congestionamento, a qual limita a transmissão em função do congestionamento percebido na rede.
A qualquer tempo, a quantidade de dados enviados e não reconhecidos dentro de uma conexão TCP não deve exceder o mínimo entre a janela de congestionamento e a janela do receptor.
Janela máxima = MIN(Janela de congestionamento, Janela do receptor)
Funcionamento do controle de congestionamento TCP
A ideia do controle de congestionamento é permitir que o TCP transmita o mais rápido possível, desde que não perda segmentos. Para isto, a conexão TCP começa com uma janela de congestionamento de tamanho pequeno, visando sondar a existência de banda, e vai aumentando o tamanho da janela até que ocorra uma perda. Quando isto acontece, o TCP reduz o tamanho da janela para um nível seguro, e volta a aumentá-la, sondando novamente a existência de banda.
Partida Lenta
Assim que a conexão TCP é estabelecida, a aplicação remetente escreve bytes no buffer de envio do TCP emissor. O TCP agrupa os bytes em segmentos de tamanho MSS e envia para a camada rede para transmissão.
Inicialmente a janela de congestionamento é igual a um MSS. Isto significa que o TCP envia um segmento e espera por um reconhecimento. Se este segmento foi reconhecido antes do estouro do temporizador, o TCP dobra o tamanho da janela de congestionamento, passando a enviar dois segmentos. Se receber reconhecimentos novamente, volta a dobrar o tamanho da janela para quatro, e assim por diante.
O TCP continua este procedimento enquanto:
- a janela de congestionamento estiver abaixo de um valor de limiar;
- os reconhecimentos chegarem antes do estouro do temporizador.
Esta fase do controle de congestionamento é chamada de partida lenta, na qual a janela inicia com o valor de MSS e aumenta de forma exponencial.
Prevenção de Congestionamento
A fase de partida lenta termina quando o tamanho da janela atinge o valor de limiar (threshold). A partir deste momento a janela continua a crescer linearmente, um MSS para cada RTT. Esta fase é chamada de prevenção de congestionamento.
Se houver um estouro de temporização, o valor do limiar é ajustado para a metade do valor corrente da janela, e a janela é ajustada para um MSS, reiniciando o processo de partida lenta.
Fonte: [1]
O estouro da temporização é um evento drástico, pois indica que não estão chegando reconhecimentos vindos do lado do receptor. Isto justifica reiniciar o processo de partida lenta, diminuindo o tamanho da janela de congestionamento para um MSS.
Retransmissão rápida e AIMD
Caso o TCP receba três reconhecimentos duplicados antes de um estouro de temporizador, o mesmo saberá que o outro lado deve ter recebido pacotes fora de ordem, o que sugere que o pacote anterior tenha sido perdido ou está atrasado.
Neste caso, o emissor retransmite imediatamente o pacote solicitado, o que é chamado retransmissão rápida. Além disto, o TCP ele reduz o tamanho da janela de congestionamento para a metade de seu valor corrente e volta a crescer linearmente. Este algoritmo é chamado de aumento aditivo, dimuinuição multiplicativa (AIMD - additive-increase, multiplicative-decrease).
Fonte: [4].
A filosofia do AIMD é que três reconhecimentos duplicados indica que a rede é capaz de entregar alguns segmentos. Entretanto, um estouro de temporizador antes de três reconhecimentos duplicados é mais alarmante e justifica reiniciar a partida lenta.
Ao longo do tempo de vida de uma conexão TCP, a variação da janela de congestionamento segue um padrão de continuidade aumentando e diminuindo, como mostrado no formato dente de serra do AIMD.
Referências
- ↑ 1,0 1,1 1,2 1,3 1,4 KUROSE, J.F; ROSS K. W. Redes de Computadores e a Internet: Uma abordagem top-down, São Paulo: Pearson, 2010.
- ↑ 2,0 2,1 2,2 STEVENS, W. S.; FENNER, B.;RUDOFF, A. M. Programação de Rede UNIX. Porto Alegre: Bookman, 2005.
- ↑ STRETCH, J. TCP Flags: PSH and URG: http://packetlife.net/blog/2011/mar/2/tcp-flags-psh-and-urg/
- ↑ http://alpha.tmit.bme.hu/meresek/lantcp_eng.htm#tcpretrasmission
--Evandro.cantu (discussão) 17h12min de 20 de março de 2015 (BRT)