# Redes de computadores/Multiplexação e demultiplexação

Situada entre as camadas de aplicação e de rede, a camada de transporte provê uma comunicação processo a processo. Para tal, a camada de transporte utiliza o conceito de portas, que é, na verdade, um número que identifica qual processo deverá se encarregar da informação trazida por aquele pacote. Na prática, o aplicativo informa ao sistema operacional que estará escutando uma determinada porta e então todos os pacotes daquele protocolo (UDP ou TCP) serão repassados àquele processo. A Demultiplexação é a entrega dos dados de um segmento da camada de transporte à porta correta. "O trabalho de reunir, no hospedeiro de origem, porções de dados provenientes de diferentes portas, encapsular cada porção de dados com informações do cabeçalho (que mais tarde serão usadas na demultiplexação) para criar segmentos, e passar esses segmentos para a camada de rede é denominado multiplexação".(KUROSE; ROSS, 2006, p. 148).

## Multiplexação e Demultiplexação na camada de transporte

Sabe-se que o serviço de multiplexação e o de demultiplexação é de extrema importância para todas as redes de computadores. No entanto, aqui será enfatizado seu uso na camada de transporte.
A camada de transporte, em um hospedeiro de destino, recebe segmentos da camada de rede que fica abaixo dela (isso acontece, analisando uma abordagem top-down), a qual tem o dever de entregar todos os dados desses segmentos ao processo da camada de aplicação, que também roda nesse hospedeiro. Porém, o que acontece na realidade é que a camada de transporte não entrega os segmentos a um processo, mas sim em um socket (porta) intermediário. Onde cada socket tem um identificador exclusivo, que depende de o Socket ser TCP ou UDP.
O direcionamento a uma porta correta de um segmento, é feito a partir da análise de um conjunto de campos que se localiza no segmento. Nesse campo encontra-se a porta destinatária, a qual o segmento será direcionado pela camada de transporte. Esse direcionamento a porta correta é denominado de demultiplexação.
Define-se multiplexação como sendo a tarefa de reunir pedaços de dados, vindos de diferentes portas (no hospedeiro de origem), encapsulando esses pedaços com o conjunto de campos para criar segmentos e entregá-los a camada de rede. A transferência de dados pode ser feita por: UDP (não orientada para conexão) ou TCP (orientada para conexão). Caso seja feita por UDP, o socket UDP é identificado por uma tupla com dois elementos: endereços IP de destino e um número de porta de destino; por outro lado seja feita por TCP, o Socket TCP é identificado por uma tupla com quatro elementos: endereço IP de origem, número da porta de origem, endereço IP de destino e número da porta de destino.

## Multiplexação/demultiplexação não orientada para conexão

A porta UDP pode ser criada a partir de uma implementação, na qual pode se designar um número de porta específico ou mesmo deixar que seja designado um número de porta ao Socket pela camada de transporte. Logicamente isso, dependerá da escolha do implementador. Em geral, o lado servidor de uma aplicação designa um número de porta específico, enquanto o lado cliente da aplicação deixa essa escolha livre e transparente para a camada de transporte.
Com isso, entende-se que mesmo que dois ou mais segmentos tenham endereços IP ou número de porta fonte diferentes eles poderão ser direcionados ao mesmo processo de destino, caso tenham o mesmo número IP e mesmo número de porta de destino pela mesma porta de destino.

## Transporte Orientado Para Conexão: TCP

O protocolo TCP é, sem dúvidas, um dos mais importantes protocolos utilizados atualmente. Esse protocolo fornece um serviço de entrega de pacotes confiável e orientado para conexão, ou seja, todos os aplicativos que utilizam o TCP como protocolo de transporte estabelecem uma conexão antes de começar a trocar dados, além de contar com serviços como detecção de erros, retransmissões, reconhecimento cumulativo, temporizadores e campos de cabeçalho para números de seqüência e de reconhecimento.
Ao contrario do UDP para mandar dados através do TCP é necessário a abertura de uma conexão fim-a-fim, ou seja o TCP suporta comunicação apenas entre dois hosts por vez. Uma sessão TCP é inicializada através de um processo conhecido como 'three-way handshake', que consiste em três pacotes de estabelecimento de conexão, sendo um pacote SYN enviado pelo cliente que consiste em um segmento TCP especial que não contem nenhum dado da camada de aplicação mas com o flag SYN ativado. Além disso o cliente escolhe aleatoriamente um numero de seqüência inicial e coloca esse número no campo de numero de seqüência do segmento SYN inicial. Quando o servidor recebe o segmento SYN ele aloca buffers e variáveis TCP necessárias a conexão e envia um segmento de aceitação de conexão ao TCP cliente. Esse segmento é chamado SYNACK. Ao receber o segmento SYNACK o cliente também reserva buffers e variáveis para a conexão. O cliente então envia ao servidor mais um segmento que reconhece o segmento de confirmação da conexão do servidor, o bit SYN é ajustado para 0 e a conexão já esta estabelecida. Esse processo sincroniza os números de seqüência e oferece informações de controle necessárias para estabelecer uma conexão virtual entre os dois hosts. Depois de concluído o 'tree-way handshake' inicial, os segmentos são enviados e confirmados de forma seqüencial entre os hosts remetente e destinatário. Um processo de handshake semelhante é usado pelo TCP antes de fechar a conexão para verificar se os dois hosts acabaram de enviar e receber todos os dados.
O TCP recebe os dados de aplicação e processa esses dados como um conjunto de bytes, os mesmos são agrupados em segmentos que o TCP numera em seqüência para a entrega. Apos receber os dados de aplicação o TCP direciona esses dados para um buffer de envio da conexão (reservado durante o estabelecimento da conexão) e vai criando segmentos e enviando para a rede. A quantidade máxima retirada do buffer e colocada em um segmento é limitada pelo MMS (tamanho máximo do segmento).
O TCP utiliza o conceito de portas, que permite que vários programas estejam em funcionamento, ao mesmo tempo, no mesmo computador, trocando informações com um ou mais serviços/servidores.
Algumas das principais características do TCP e que faz com que ele seja tao utilizado são citadas a seguir:
* Garante a entrega de datagramas IP: Esta talvez seja a principal função do TCP, ou seja, garantir que os pacotes sejam entregues sem alterações, sem terem sido corrompidos e na ordem correta. O TCP tem uma série de mecanismos para garantir esta entrega.
* Garante o seqüenciamento adequado e entrega ordenada de dados segmentados: Esta característica refere-se a função de dividir grandes arquivos em pacotes menores e transmitir cada pacote separadamente. Os pacotes podem ser enviados por caminhos diferentes e chegar fora de ordem. O TCP tem mecanismos para garantir que, no destino, os pacotes sejam ordenados corretamente, antes de serem entregues ao programa de destino.
* Verifica a integridade dos dados transmitidos: Usando cálculos de soma de verificaçao o TCP faz verificações para garantir que os dados não foram alterados ou corrompidos durante o transporte entre a origem e o destino.
* Envia mensagens positivas dependendo do recebimento bem-sucedido dos dados. No destino, o TCP recebe os pacotes, verifica se estão OK e, em caso afirmativo, envia uma mensagem para a origem, confirmando cada pacote que foi recebido corretamente. Caso um pacote não tenha sido recebido ou tenha sido recebido com problemas, o TCP envia uma mensagem ao computador de origem, solicitando uma retransmissão do pacote. Com esse mecanismo, apenas pacotes com problemas terão que ser reenviados, o que reduz o tráfego na rede e agiliza o envio dos pacotes.
* Oferece um método preferencial de transporte de programas que devem usar transmissão confiável de dados baseada em sessões: Ou seja, o TCP é muito mais confiável do que o UDP e é indicado para programas e serviços que dependam de uma entrega confiável de dados.

## Transporte Não Orientado Para Conexão: UDP

O UDP é um protocolo usado para o transporte rápido de dados entre hosts TCP/IP. Porém o UDP não fornece garantia de entrega e nem verificação de dados. De uma maneira simples, podemos dizer que o protocolo UDP manda os dados para o destino sem a necessidade de apresentação entre as unidades remetentes e destinatária antes de enviar o segmento, porem se vai chegar, e sem erros, é impossível saber (o UDP fornece verificação de erro porém nada faz para corrigir o erro, apenas informa a aplicação que determinado pacote é corrupto). O UDP não garante a entrega ou verifica o seqüenciamento para qualquer pacote. Uma outra solução bastante utilizada ultimamente é a inserção da confiabilidade na própria aplicação (adicionando mecanismos de reconhecimento e de transmissão embutidos na aplicação) permitindo assim que ela tire proveito de ambas as alternativas, ou seja, os processos de aplicação se comunicam de maneira confiável sem ter que se sujeitar as limitações da taxa de transmissão impostas pelo mecanismo de controle de congestionamento impostas pelo TCP.
Alguns dos principais motivos pelo qual o UDP pode ser preferível são:
* Melhor controle no nível de aplicação sobre quais dados são enviados e quando: como ele não possui controle de congestionamento (como ocorre no TCP), não ocorre atraso no envio do pacote. Não possui o serviço de confirmação de recebimento que pode atrasar a transmissão se alguns pacotes forem perdidos, e é compatível com aplicações de tempo real onde a velocidade é mais importante que a confiabilidade na entrega.
* Não há estabelecimento de conexão: O UDP apenas envia os dados sem perder tempo tentando abrir conexões (como ocorre no TCP) esse é um dos motivos pelo qual DNS roda sobre UDP.
* Não há estados de conexão: Usado pelo TCP para garantir a entrega confiável de dados (esses estados inclui buffers de envio e recebimento, parâmetros de controle de congestionamento e etc), por isso um servidor com uma aplicação especifica pode suportar um numero muito maior de clientes ativos quando a aplicação roda sobre UDP ao invés de TCP.
* Pequena Sobrecarga de Cabeçalho de Pacote: O TCP possui 20 bytes de sobrecarga de cabeçalho enquanto o UDP so possui 8 bytes.
Algumas das aplicações mais importantes que utilizam o UDP são:
* Atualização de tabelas de roteamento com protocolo RIP.
* Transferir dados de gerenciamento de rede, que normalmente funcionam quando a rede esta sobrecarregada e é difícil conseguir transferência confiável devido ao controle de congestionamento.
* O DNS também roda sobre o UDP.
* É bastante utilizado em aplicações multimídia como telefone por internet, vídeo conferência em tempo real e recepção de áudio e vídeo armazenados.

## Mecanismos de Controle de Congestionamento

Podemos distinguir mecanismos de controle de congestionamento conforme a camada de rede ofereça ou não assistência explícita à camada de transporte, com finalidade de controle de congestionamento. Sabendo que 'Janela de Congestionamento' é um parâmetro que impõe uma limitação a taxa a qual o remetente pode enviar tráfego para dentro da rede, (especificamente a quantidade de dados não reconhecidos em um hospedeiro não pode exceder o mínimo da janela de congestionamento) podemos dividir o controle de congestionamento em dois modos:
* Controle de congestionamento fim-a-fim: Nesse método a camada de rede não fornece nenhum suporte explícito à camada de trasporte, e o congestionamento da rede é intuída pelos sistemas finais com base na observação do comportamento da rede (perda de pacotes). Esse é o metodo utilizado pelo protocolo TCP.
* Controle de congestionamento assistido pela rede: com esse método os roteadores fornecem realimentação de informações ao remetente a respeito do congestionamento da rede. O controle de congestionamento assistido pela rede tem dois modos de operação. São eles:
** Realimentação Direta: Pacote enviados de um roteador da rede a um remetente (como se fosse um pacote de congestionamento dizendo: “estou congestionado”)
** Realimentação Indireta: Ocorre quando um roteador marca/atualiza um campo em um pacote que esta indo do remetente ao destinatário para indicar o congestionamento e com isso o destinatário informa ao remetente sobre o congestionamento. Esse método possui a desvantagem de perder, no mínimo, o tempo de ida e volta de um pacote, para avisar ao remetente sobre o congestionamento.

## Servidores Web e o TCP

Este é um cenário bastante interessante para se entender os princípios da multiplexação e demultiplexação no TCP. Observe uma ilustração de uma situação típica, onde vários clientes se conectam a um servidor WEB através da porta 80.
Em virtude de o TCP ser identificado por uma tupla de 4 (quatro) elementos, todas as conexões serão corretamente multiplexadas/demultiplexadas.
Os pacotes que saem dos hospedeiros clientes possuem sempre o IP de destino B e porta de destino 80. Isto é exatamente o esperado em se tratando de servidores WEB.
Consideremos primeiramente o processo cliente (navegador) rodando no hospedeiro A. Apesar de este processo ter escolhido a mesma porta de origem do processo rodando em C (porta origem x), os pacotes de A e C serão corretamente demultiplexados, pois o servidor WEB ainda pode diferenciar os pacotes devido ao campo IP de origem. Analogamente, também não haverá problema na identificação de pacotes de duas aplicações rodando no mesmo hospedeiro cliente (como ocorre em C). Os pacotes serão diferenciados através do número da porta de origem, que deve ser diferente para cada um dos processos(neste exemplo, temos x e y). Uma breve conclusão é que o servidor identifica os pacotes pelo campo 'IP de origem', e duas aplicações no mesmo cliente se diferenciam pela campo 'porta de origem'.
O servidor WEB, por sua vez, tem duas abordagens para gerenciar estas conexões. Ele pode, a cada nova requisição, criar um novo thread (inserido em um único grande processo), ou criar um novo processo. Threads são mais eficientes, uma vez que exigem/alocam menos recursos de hardware para serem executados. Observe que nas duas abordagens, o servidor designará um socket único a cada thread/processo, que na prática, designa a porta pela qual os dados passam da aplicação à camada de transporte.

## Algoritmo de Controle de Congestionamento

O principal objetivo do controle de congestionamento é reduzir a taxa em que um remetente envia pacotes na rede. Normalmente isso é conseguido diminuindo o tamanho da janela de congestionamento de todos os remetentes quando a rede esta congestionada (ocorre perdas de pacotes).
Alguns dos principais algoritimos usados no controle de congestinamento são:
* Diminuição Multiplicativa: Nessa abordagem o TCP diminui a janela de congestionamento pela metade toda vez que houver uma nova perda de pacotes. O valor da janela de congestionamento pode atingir um valor mínimo igual a 1 MSS.
* Aumento Aditivo: Esse método é utilizado toda vez que não há congestionamento, o principio desse método é que se nenhum congestionamento for detectado, provavelmente há largura de banda disponível e que pode ser usada adicionalmente pelo TCP. Nessas circunstancias o TCP aumenta sua janela de congestionamento lentamente para verificar se há largura de banda adicional disponível no caminho fim-a-fim. Isso é conseguido incrementando a janela de congestionamento cada vez que um novo reconhecimento é recebido tendo como meta aumentar a mesma de 1 MSS a cada tempo de viagem de ida e volta.
* Partida Lenta: No inicio de uma conexão o TCP inicia o valor da janela de congestionamento em 1 MSS. Nesse caso a taxa de aumento da mesma aumenta exponencialmente, duplicando seu valor de janela de congestionamento a cada RTT (Round Trip Time). Esse aumento exponencial continua até ocorrer o primeiro evento de perda.

## Referências

KUROSE; ROSS. Redes de Computadores e a Internet: Uma abordagem top-down. São Paulo: Pearson Addison Wesley, 2006