Baixe o app para aproveitar ainda mais
Prévia do material em texto
Módulo 3: CAMADA DE TRANSPORTE 3.1: Serviços da camada de transporte Um protocolo da camada de transporte fornece comunicação lógica entre processos que rodam em hosts diferentes, independente da infraestrutura física entre os hosts. Isso significa que: ➢ No host remetente, o protocolo vai quebrar as mensagens que chegam da camada de aplicação em segmentos menores e vai adicionar um cabeçalho em cada pedaço. O protocolo, então, passa esses segmentos para a camada de rede, que vai encapsular eles em datagramas e enviar ao destino. ➢ No host destinatário, a camada de rede extrai os segmentos dos datagramas e os envia para a camada de transporte. Nela, os segmentos vão ser remontados em mensagens, que serão enviadas à camada de aplicação. Camada de Transporte x Camada de Rede Enquanto a camada de transporte faz a comunicação lógica entre processos, a camada de rede faz a comunicação lógica entre hosts. ➢ Os protocolos de rede transportam as mensagens entre hosts. ➢ Os de transporte agem dentro dos hosts, levando as mensagens dos processos para a camada de rede e vice-versa. Os protocolos da camada de transporte são limitados pelos protocolos da camada de rede: se o protocolo da rede não der garantias contra atrasos ou de largura de banda, por exemplo, o protocolo de transporte também não pode dar essas garantias para as aplicações. Porém, tem alguns serviços que um protocolo de transporte pode oferecer mesmo se o protocolo da rede não o fizer. Exemplos: ➢ Garantir confiabilidade na transferência de dados (mesmo se o protocolo de rede perder, embaralhar ou duplicar dados) . ➢ Garantir segurança na transferência de dados, usando criptografia para proteger os segmentos. 3.2: Multiplexação e Demultiplexação Um processo pode ter um ou mais sockets e, por isso, a camada de transporte não entrega os dados a um processo diretamente, mas a um socket intermediário. Cada socket dentro de um host vai ter um identificador, que depende se ele é UDP ou TCP. ➢ Multiplexação representa os serviços do protocolo de transporte relacionados ao host remetente. ➢ Demultiplexação representa os serviços do protocolo de transporte relacionados ao host destinatário. (ambos descritos no tópico anterior, 3.1) O cabeçalho do segmento de transporte adicionado na multiplexação precisa de um campo com o número da porta de origem e outro com o número da porta de destino, cada um com 16 bits. MUX e DEMUX para UDP Um socket UDP vai ser sempre identificado pela seguinte tupla: 1. Endereço IP de destino 2. Número da porta (socket) de destino Logo, todos os segmentos que chegarem com esses mesmos identificadores serão direcionados para o mesmo socket, independente dos IPs e números de porta de origem. Então, por que se coloca o endereço IP e a porta de origem numa conexão UDP? Serve como um endereço de retorno, para caso o host de destino queira enviar mensagens de volta ao host de origem. Aí então os endereços IP e os números de porta vão inverter as ordens (o de destino vira de origem e o de origem vira destino). MUX E DEMUX para TCP Um socket TCP vai ser sempre identificado pela seguinte tupla quádrupla: 1. Endereço IP de origem 2. Número da porta de origem 3. Endereço IP de destino 4. Número da porta de destino Quando uma mensagem de requisição de conexão chega no host de destino, uma nova socket é criada e ela será identificada por esses 4 fatores. Assim, todos os segmentos que chegarem depois com essas mesmas 4 informações serão direcionadas para essa socket. 3.3: UDP O UDP adiciona muito pouco ao IP, além do processo de MUX e DEMUX. Ele pega a mensagem vinda da camada de aplicação, anexa os endereços das portas de origem e destino e adiciona mais dois campos no cabeçalho: comprimento e checksum. Depois, passa o segmento à camada de rede, que será encapsulado em um datagrama, e entrega ele ao host de destino pela técnica do menor esforço. Relembrando algumas características do UDP: ➢ Não é orientado a conexão: Ele não faz uma apresentação entre as entidades do remetente e destinatário antes de enviar uma mensagem. ➢ A transferência de dados não é confiável: Ele não detecta perda de pacotes nem troca de ordem. ➢ Não faz controle de fluxo nem de congestionamento: Não controla a taxa de transferência para evitar transbordar o buffer do destino nem pra evitar congestionar a rede. Então porque alguém escolheria o UDP? Para aplicações que requerem uma taxa mínima de envio, não toleram muito atraso e aguentam uma certa perda de dados. Como não há estabelecimento de conexão no UDP, já economiza tempo. Além disso, o UDP não monitora parâmetros de controle de congestionamento e transferência de dados, o que permite a um servidor que use UDP numa aplicação suportar um número muito maior de usuários simultâneos. Processos em que se usa UDP: ➢ Recepção multimídia (apesar de estar crescendo a quantidade de uso por TCP) ➢ Telefonia por internet ➢ Gerenciamento de rede (SNMP) ➢ Protocolo de roteamento (RIP) ➢ Tradução de nome (DNS) Estrutura do segmento UDP O cabeçalho do UDP tem 4 campos, cada um com 16 bits: os dois primeiros são os campos de porta de origem e destino e os dois últimos são o comprimento e o checksum. ➢ O comprimento especifica o número de bytes no segmento UDP (cabeçalho + dados). ➢ Já o checksum é um campo usado pelo host receptor pra checar se houve erro na transmissão de dados. Todas as palavras de 16 bits do segmento vão ser somadas, e depois se faz o complemento de 1 dessa soma. Esse resultado vai ser armazenado no campo checksum e vai ser analisado para checar se houve alguma alteração nos bits do segmento. Além dos campos de cabeçalho, o UDP possui mais um campo para armazenar os dados da mensagem. 3.4: PRINCÍPIOS DA TRANSFERÊNCIA CONFIÁVEL DE DADOS Mesmo se a camada de transporte usar um protocolo de transferência de dados confiável, a camada de rede pode usar um canal não confiável para transferir esses dados. A seguir temos o funcionamento da transferência confiável de dados dependendo do nível de confiabilidade do canal. Vamos considerar um protocolo de transporte confiável pelo nome rdt (reliable data transfer). rdt1.0: Canal de transferência 100% confiável No lado remetente, o rdt recebe dados da camada de aplicação pelo comando rdt_send(data). Esse evento vai fazer o protocolo colocar os dados em um pacote, pelo make_pkt(data) e depois enviá-lo pelo canal, pelo udt_send(packet). No lado destinatário, o rdt recebe um pacote do canal da rede pelo rdt_rcv(packet), depois extrai os dados do pacote pelo extract(packet,data) e entrega pra camada de aplicação, pelo deliver_data(data). rdt2.0: Transferência com erros de bits Os protocolos que lidam com erros de bits são conhecidos como ARQ (Automatic Repeat reQuest). Para manipular esses erros em um ARQ, são necessárias 3 coisas: ➢ Detecção do erro. ➢ Respostas de reconhecimento positivo ou negativo do destinatário pro remetente (positivo: ACK, negativo: NAK). ➢ Retransmissão de pacotes do remetente pro destinatário. No lado remetente, a FSM tem dois estados: esperar chamada de cima e esperar ACK ou NAK. No primeiro estado, a única diferença desse rdt pro 1.0 é que, quando ele for criar o pacote, será adicionado o campo checksum. Aí então ele passa pro segundo estado, no qual ele pode receber do destinatário uma mensagem ACK, que faz ele voltar ao primeiro estado, ou uma mensagem NAK, que faz ele reenviar o último pacote e permanecer no mesmo estado esperando por outra resposta. obs: Quando ele está no estado de espera por ACK ou NAK, ele não pode receber mensagens da camada superior. Por isso o rdt2.0 é conhecido como um protocolo stop-and-wait. No lado destinatário, ele vai receber o pacote e analisar se está corrompido, pelo checksum. Se não estiver corrompido, ele segue o procedimento normal de enviar os dados pra camada de aplicação e depois faz um pacote da mensagem ACK e envia. Se estiver corrompido, ele só empacota e envia a mensagem NAK pro remetente e espera. rdt2.1: Transferência com erros no ACK ouNAK Solução: O destinatário adiciona um campo checksum nos pacotes de ACK ou NAK, fazendo com que o remetente saiba se eles estão corrompidos ou não. Além disso, o remetente também adiciona nos pacotes enviados um campo que contém um número de sequência (0 ou 1). Assim, quando ele receber um ACK ou NAK corrompido, ele reenvia o pacote com o mesmo número de sequência que foi enviado no anterior, fazendo o destinatário saber que aquela mensagem é um reenvio. Depois, o destinatário envia novamente sua resposta e, quando o remetente finalmente receber um ACK não corrompido, ele envia um pacote novo, com outro número de sequência, indicando que é um pacote diferente do anterior. No lado remetente, ele envia um pacote com número de sequência 0 e depois fica esperando a resposta. Se ela estiver corrompida ou for um NAK, ele reenvia o pacote 0. Se for um ACK, ele passa a esperar um pacote 1 da camada de aplicação. Quando receber, ele envia o pacote pro destinatário e fica esperando resposta, repetindo o processo do pacote 0. No lado destinatário, sempre que ele receber um pacote corrompido, ele vai enviar uma mensagem NAK pro remetente (1 e 3). Já quando ele receber um pacote não-corrompido e com número de sequência diferente, seja 0 ou 1, ele vai mandar os dados pra camada de aplicação, enviar uma mensagem ACK pro remetente e depois esperar um novo pacote com o número de sequência contrário (2 e 5). Já se ele receber um pacote com o mesmo número de sequência que recebeu antes, é porque o ACK mandado anteriormente foi corrompido, então ele manda novamente a mensagem ACK (4 e 6). Ou seja, no 4 ele recebeu o mesmo pacote que foi recebido no 2, enquanto no 6 foi recebido o mesmo pacote do 5. rdt2.2: Igual ao 2.1, mas não usa NAK O processo é igual, a única coisa que muda é que o ACK vai ser associado a um valor 0 ou 1. No lado remetente, ele vai checar a resposta com o isACK(). Se foi enviado um pacote 0 pelo remetente, por exemplo, e o isACK for 0 (igual ao pacote), é equivalente a um ACK e, se for 1 (contrário ao pacote), é equivalente a um NAK. No lado destinatário, ele vai enviar um ACK para cada pacote recebido e processado, com o mesmo número de sequência. Se o pacote recebido estiver corrompido ou for um reenvio, essa checagem vai ser feita em um mesmo self-loop ao invés de dois: vai ser enviado um ACK com número igual ao do último pacote processado. Assim, se for um pacote novo corrompido, o remetente vai interpretar como um NAK. Já se for um reenvio, o remetente vai interpretar como um ACK. rdt3.0: Transferência com erros de bits e com perda de dados Teremos agora que detectar se houve perda de pacotes e como proceder nesses casos. Para fazer essa detecção, vai ser preciso um novo mecanismo de protocolo no remetente, pois tanto se o pacote que ele enviou for perdido quanto se o ACK ou NAK for perdido, ele não vai obter resposta. Uma solução seria o remetente esperar o tempo máximo possível do RTT + o tempo de processamento no destinatário para então reenviar o pacote, mas é muito difícil definir com certeza esse tempo. Logo, a solução ideal é o remetente estimar um valor de tempo para o qual pode ter acontecido uma perda, aí então ele reenvia o pacote. Se o pacote inicial sofrer um atraso longo, sem perda, vai acontecer de ter pacotes de dados duplicados no canal, mas as funcionalidades do rdt2.2 já permitem lidar com esse tipo de coisa. Assim, o remetente vai precisar de um temporizador de contagem regressiva e, com ele, realizar as seguintes tarefas: ➢ Acionar o temporizador sempre que um pacote for enviado. ➢ Quando o temporizador for interrompido, realizar as ações necessárias. ➢ Parar o temporizador. No lado remetente, sempre que um pacote for enviado, vai ser acionado o temporizador, enquanto sempre que ele receber um ACK, o temporizador vai parar. No estado de espera do ACK, sempre que ele receber um pacote corrompido ou um NAK, ele vai esperar o temporizador dar timeout e vai reenviar o pacote (onde tem as setas). Já nos estados de espera da camada de aplicação, os self-loops vão indicar que não houve perda, e o pacote reenviado foi devido a um atraso longo. Por isso, o remetente recebe uma mensagem de resposta duplicada, que não vai interferir em nada no estado atual. No lado destinatário, eu acredito que a FSM é igual a do rdt2.2, pois ele vai continuar com as mesmas funcionalidades de receber e enviar pacotes e detectar reenvios. Algumas possibilidades de ocorrência do rdt3.0: O problema com o protocolo rdt3.0 é o seu desempenho. Por ser um protocolo stop-and-wait, o remetente só envia um novo pacote quando recebe um ACK do destinatário. Uma solução pra isso é o método Pipelining (ou Paralelismo), no qual o remetente envia vários pacotes de uma vez e, a cada resposta que chega de um pacote, ele envia outro. Isso gera algumas mudanças na transmissão: ➢ Precisa ter mais números de sequência além de 0 e 1, pois vão ter mais pacotes não reconhecidos em trânsito. ➢ O remetente e o destinatário vão precisar reservar buffers para mais de um pacote. Existem 2 formas genéricas de protocolos Pipeline: Go-Back-N e Repetição Seletiva. Go-Back-N (GBN) Num protocolo GBN, existe uma quantidade máxima N de pacotes não reconhecidos que são permitidos na tubulação. Com relação a nova faixa dos números de sequência, a gente pode classificar ela em 4 partes pela visão do remetente: base é o número de sequência do pacote mais antigo que foi enviado, mas não foi reconhecido e nextseqnum é o número de sequência do próximo pacote a ser enviado. Essa faixa da janela tem tamanho N e engloba todos os pacotes que podem estar dentro da tubulação de forma simultânea (tanto os que já foram enviados quanto os que ainda não foram). À medida que mais pacotes são reconhecidos no destinatário, essa janela vai se deslizando pra direita e, por isso, o GBN também é conhecido como o protocolo da janela deslizante (sliding-window protocol). Assim, o número de sequência é definido por um campo de k bits no cabeçalho. No lado remetente, vou explicar as ações de 1 a 5: A 1 representa o primeiro pacote a ficar pronto pro envio, quando não tem nenhum pacote pendente no canal (é o nextseqnum). Na 2, esse pacote vai ser enviado pelo canal e, para isso, precisa checar se ele está inserido dentro daquela janela. Se ele estiver, o pacote é enviado pro destinatário e, se não estiver, ele volta pra camada de aplicação. Se não tiver nenhum pacote pendente no canal antes dele, o temporizador é iniciado e o nextseqnum pega o próximo pacote na fila. Na 3, o temporizador dá timeout e é reinicializado, mandando novamente todos os pacotes que estão pendentes no canal. Na 4, um ACK é recebido e o pacote base passa pro pacote seguinte ao que corresponde ao ACK. Se essa nova base for o nextseqnum, o temporizador vai parar e, se for um pacote já enviado, ele é reinicializado. Por último, na 5, o remetente recebe um pacote corrompido e não realiza mais nenhuma ação, eventualmente caindo no timeout. No lado destinatário, ele vai controlar a ordem de chegada dos pacotes com o campo expectedseqnum. Se o pacote que chegou estiver na ordem correta, ele vai seguir o procedimento padrão: extrair os dados do pacote, enviar eles pra camada de aplicação, mandar um ACK pro remetente e atualizar o valor do expectedseqnum. Se ele chegou fora de ordem ou com algum outro erro, o destinatário só descarta o pacote e reenvia o ACK do último pacote que foi bem recebido. Porque o destinatário descarta também os pacotes que chegam fora de ordem, e não guarda na memória buffer? Porque pelo protocolo do remetente, se der algum erro em um pacote, todos os pacotes pendentes serão enviados. Então aquele mesmo pacote que o destinatário guardou no buffer vai chegar nele de novo. Repetição Seletiva (SR) O próprio GBN pode ter problemas de desempenho: Ele permite que tenham muitos pacotes pendentes na rede e, se der um único erro, vários pacotes serão retransmitidos desnecessariamente. Por isso, os protocolos de Repetição Seletiva reenviamsomente os pacotes individuais que derem erro. As diferenças para o GBN são duas: cada pacote agora tem seu próprio temporizador e, se um pacote chegar fora de ordem, ele vai ser armazenado no buffer do destinatário até chegarem os outros anteriores. No lado remetente, quando o send_base é reconhecido, a janela desliza até o próximo pacote pendente. No lado destinatário, ele vai guardar no buffer os pacotes recebidos fora de ordem e, quando receber o send_base do remetente, o conjunto de pacotes é mandado para a camada de aplicação. As janelas do remetente e do destinatário nem sempre coincidem. Se o destinatário reconheceu um pacote, por exemplo, mas o ACK que ele mandou for perdido, o remetente vai reenviar o pacote quando der timeout (é o caso da imagem de cima). Quando o destinatário receber novamente esse pacote, vai reconhecer ele de novo e enviar outro ACK. O tamanho da janela deve ser menor ou igual à metade do tamanho da faixa dos números de sequência para protocolos SR. 3.5: TCP O TCP usa todos os mecanismos do tópico anterior: campo checksum, temporizadores, número de sequência, reconhecimento positivo e negativo e paralelismo/pipelining. Relembrando algumas características do TCP: ➢ Ele é orientado a conexão, ou seja, os dois hospedeiros se “apresentam” antes de iniciar a transferência de dados. ➢ É um serviço full-duplex: Os dados podem fluir em ambos sentidos entre os hospedeiros, simultaneamente. ➢ É uma conexão ponto a ponto: Só são permitidos dois hospedeiros. ➢ Tem transferência confiável de dados e faz controle de fluxo e de congestionamento. Como a conexão TCP é estabelecida? Através de um processo denominado apresentação de três vias (3-way handshake), no qual o cliente manda um primeiro segmento TCP, o servidor responde com outro e o cliente manda um terceiro. Esse último segmento pode já ter algum dado da camada de aplicação. Depois do estabelecimento da conexão, os dados são recebidos no TCP cliente pelo socket e são direcionados para o buffer de envio da conexão, que é um buffer reservado na apresentação de três vias. E aí de tempos em tempos, o TCP pega pedaços de dados desse buffer e envia pra camada de rede. Além do buffer de envio, também é estabelecido um buffer de recepção para cada host na fase de conexão. Como o TCP determina a quantidade de dados que vai em cada segmento? O máximo de dados que pode ser colocado em um segmento é denominado MSS (maximum segment size). Esse valor depende do MTU (maximum transmission unit), que é o tamanho máximo da unidade (ou quadro) do enlace que pode ser enviada pelo remetente. O segmento de dados + o cabeçalho dele têm que caber no MTU, por isso precisa descobrir o MTU primeiro para depois definir o MSS. Estrutura do segmento TCP O segmento TCP é dividido em um campo de dados e um cabeçalho. O cabeçalho possui a seguinte estrutura: ➢ Tem as portas de origem e destino e o campo checksum, que funcionam igual ao UDP. ➢ O campo comprimento do cabeçalho tem 4 bits e sua função é auto-explicativa. ➢ A janela de recepção é usada no controle de fluxo e indica quantos bytes o destinatário pode aceitar. ➢ O campo de opções pode ser usado pra alterar o MSS, para marcar o tempo ou outras coisas. Ele nem sempre é usado e tem tamanho variável. ➢ No campo de flags de 6 bits temos: o bit ACK, que determina se o segmento atual está agindo também como um ACK para um segmento recebido anteriormente; os bits RST, SYN e FIN são usados pra estabelecer a conexão; o PSH indica se o destinatário deve passar os dados pra camada de aplicação imediatamente e o URG indica se há dados urgentes no pacote (esses dois últimos são pouco usados). ➢ O ponteiro de emergência é usado em conjunto com a flag URG, e ele aponta para o final dos dados urgentes. ➢ Por último, o cabeçalho do TCP tem o número de sequência e o número de reconhecimento. O número de sequência é o número do primeiro byte do segmento. Por isso, se o remetente quer enviar um arquivo de 500 mil bytes e o MSS é de 1000 bytes, então vão ser enviados 500 segmentos, tendo o primeiro número de sequência 0, o segundo 1000, o terceiro 2000 e assim por diante. Já o número de reconhecimento é definido pelo host que está esperando a chegada de um segmento. Se ele já recebeu segmentos até o byte 355, por exemplo, então quando ele for mandar um pacote para o outro host, vai colocar 356 no campo. Isso também vale para pacotes que chegam fora de ordem; o número de reconhecimento continua sendo o menor byte que ainda não chegou. Como estimar o RTT pra saber o valor do timeout? Calculando o SampleRTT, que é o tempo medido do envio de um segmento até o recebimento do seu ACK. Esse valor varia pra cada segmento enviado. Logo, pra cada mudança do Sample, o valor estimado de RTT muda segundo a equação abaixo: O valor típico de alfa é 0,125. Também precisa-se ter uma medida da variabilidade da estimativa do RTT, que é medida pela equação abaixo: O valor típico de beta é 0,25. Assim, o timeout do segmento pode ser calculado por: Transferência confiável de dados do TCP Temporizador Se houver timeout: ele reenvia o segmento e reinicia o temporizador. Se houver timeout prematuro: assim que ele receber o ACK, depois do timeout, ele atualiza a base da janela, e o ACK do segmento reenviado não altera a base (afinal, tá repetido). Para evitar um timeout longo, o TCP usa a técnica de 3 ACKs duplicados para detectar segmentos perdidos: Se o emissor recebe 3 ACKs duplicados, fora o original, quer dizer que o segmento seguinte ao do ACK foi perdido, então ele reenvia o segmento antes do temporizador expirar, otimizando a transferência de dados (imagem abaixo). Segmentos fora de ordem Se chegar um ACK de um pacote 120 antes de chegar o de um pacote 100 que foi perdido, por exemplo, ele aceita todos (pois é cumulativo). Se vários segmentos chegarem em ordem no destinatário, sem lacunas, ele espera 500ms pela chegada do próximo e, se não chegar, envia um ACK cumulativo. Se chegarem segmentos fora de ordem, ele reenvia o ACK do menor número de sequência esperado (que ainda não chegou). Se chegar um segmento que preenche total ou parcialmente a lacuna, ele manda imediatamente um ACK desse segmento. Controle de fluxo Serve para não estourar o buffer do receptor. O lado direito do buffer é onde se faz a leitura dos dados, enquanto o lado esquerdo possui o tamanho que vai ser especificado no cabeçalho (na janela de recepção). Assim, o emissor limita o tamanho da sua janela de dados a esse valor. Abrir e fechar conexão Processo para abrir uma conexão (3-way handshake): 1. SYN TCP: O cliente envia seu número de sequência inicial, sem dados. 2. SYNACK: O servidor envia um ACK pra esse SYN, aloca buffers e especifica o número de sequência inicial dele. 3. ACK: O cliente recebe o SYNACK e envia um ACK, que já pode conter dados (ACK e dados podem ser enviados juntos por conta daquela flag do ACK no cabeçalho). Para fechar uma conexão: 1. Cliente fecha socket. 2. Cliente envia um FIN pro servidor. 3. Servidor recebe o FIN e envia um ACK, depois fecha a conexão do seu lado e envia outro FIN. 4. Cliente recebe FIN e envia ACK, entrando numa espera temporizada. 5. Quando o servidor recebe o ACK, a conexão é fechada. Enquanto ele não receber, ele continua mandando FINs. 3.6: Princípios de Controle de Congestionamento Congestionamento é quando muitas fontes enviam muitos dados muito rápido, ultrapassando a capacidade da rede. Os buffers dos roteadores ficam com filas grandes, gerando atrasos, ou são estourados, perdendo pacotes. Nem sempre é viável aumentar a banda passante para resolver esse problema. O que se observa é que dados retransmitidos ocupam mais a rede, apesar de chegarem menos dados úteis para o receptor. No gráfico a seguir, R representa a capacidade do enlace, Lambda(in) representa a vazão de saída do emissor e Lambda(out) é a vazão de entrada no receptor. Percebemos que, quanto mais dados o emissor manda, chega um ponto (bem menor que a metade da capacidade do enlace),que começa a decair a chegada de dados no receptor, podendo chegar a nada. O controle de congestionamento do TCP é fim-a-fim, só dá pra ser detectado pelos sistemas finais. 3.7: Controle de Congestionamento TCP Tem dois tipos de protocolo TCP: Tahoe e Reno. O controle de congestionamento também é feito usando uma janela e segue dois algoritmos para setar o tamanho dela: 1. Algoritmo de Partida Lenta: inicializa a janela com tamanho 1. Para cada ACK recebido, o tamanho dobra, ou seja, o aumento é exponencial. Se a janela ultrapassar o limiar, o algoritmo pára de executar e inicia o próximo. 2. Algoritmo de Contenção de Congestionamento: Sempre que forem enviados X segmentos (sendo X o tamanho atual da janela), ela vai incrementar o tamanho em 1. Para os dois algoritmos, se houver 3 ACKs duplicados (perda de segmento), o limiar é definido como a metade do tamanho da janela (no momento da perda). No protocolo Reno, o tamanho da janela é setado como o limiar, enquanto no protocolo Tahoe o tamanho é setado pra 1. O próximo estado será o algoritmo de Contenção de Congestionamento. Para os dois algoritmos, se tiver timeout, o limiar é definido como metade do tamanho da janela e a janela é setada para 1. O próximo estado é o algoritmo de Partida Lenta. obs: Aumentar o tamanho da janela significa aumentar a taxa de banda passante. Aumento aditivo -> aumenta a janela de 1 em 1 até a perda ser detectada. Redução multiplicativa -> reduz a janela pela metade após detectar a perda. No gráfico acima, a linha azul representa um protocolo TCP Tahoe, na qual o tamanho da janela cresce exponencialmente até chegar no limiar (8). Ao ultrapassar ele, passa a crescer de 1 em 1 até perder segmentos em 12. Então o limiar é setado como a metade da janela (6) e o tamanho da janela vai pra 1, reiniciando o processo. A linha do TCP Reno tem que começar no segundo limiar (em 6 - acredito que tá errado na imagem). Assim, o comportamento de uma janela de controle de congestionamento tem o formato dente de serra: Por que o TCP é considerado um protocolo justo? Pois se existem K sessões TCP compartilhando um enlace de taxa R, cada sessão tem uma taxa média de R/K. Porém, essa “justiça” só acontece no compartilhamento com outras sessões TCP. Se tiver um TCP e dois UDP no mesmo enlace, o TCP fica com R/2, enquanto os UDP vão dividir o outro R/2. As setinhas azuis representam o controle de congestionamento ocorrendo para a conexão 1. Esse controle também acontece do lado da conexão 2, e aí eles se encontram no meio, dividindo a banda igualmente.
Compartilhar