O handshake de 3 vias do TCP funciona assim:
Client ------SYN-----> Server
Client <---ACK/SYN---- Server
Client ------ACK-----> Server
Por que não apenas isso?
Client ------SYN-----> Server
Client <-----ACK------ Server
O handshake de 3 vias do TCP funciona assim:
Client ------SYN-----> Server
Client <---ACK/SYN---- Server
Client ------ACK-----> Server
Por que não apenas isso?
Client ------SYN-----> Server
Client <-----ACK------ Server
Respostas:
Divida o aperto de mão no que realmente está fazendo.
No TCP, as duas partes controlam o que foram enviadas usando um número de sequência. Efetivamente, acaba sendo uma contagem de bytes em execução de tudo o que foi enviado. A parte receptora pode usar o número de sequência do falante oposto para confirmar o que recebeu.
Mas o número de sequência não começa em 0. Ele começa no ISN (Número de sequência inicial), que é um valor escolhido aleatoriamente. E como o TCP é uma comunicação bidirecional, ambas as partes podem "falar" e, portanto, ambas devem gerar aleatoriamente um ISN como número de sequência inicial. O que, por sua vez, significa que ambas as partes precisam notificar a outra parte de seu ISN inicial.
Então, você acaba com essa sequência de eventos para iniciar uma conversa TCP entre Alice e Bob:
Alice ---> Bob SYNchronize with my Initial Sequence Number of X
Alice <--- Bob I received your syn, I ACKnowledge that I am ready for [X+1]
Alice <--- Bob SYNchronize with my Initial Sequence Number of Y
Alice ---> Bob I received your syn, I ACKnowledge that I am ready for [Y+1]
Observe que quatro eventos estão ocorrendo:
Na realidade, porém, os dois eventos do meio (# 2 e # 3) acontecem no mesmo pacote. O que faz um pacote ser SYN
ou ACK
simplesmente um sinalizador binário ativado ou desativado dentro de cada cabeçalho TCP , portanto, não há nada impedindo que esses dois sinalizadores sejam ativados no mesmo pacote. Portanto, o aperto de mão triplo acaba sendo:
Bob <--- Alice SYN
Bob ---> Alice SYN ACK
Bob <--- Alice ACK
Observe as duas instâncias de "SYN" e "ACK", uma de cada, nas duas direções.
Então, voltando à sua pergunta, por que não usar apenas um aperto de mão bidirecional? A resposta curta é porque um aperto de mão bidirecional permitiria apenas que uma parte estabelecesse um ISN e a outra parte o reconhecesse. O que significa que apenas uma parte pode enviar dados.
Mas o TCP é um protocolo de comunicação bidirecional, o que significa que qualquer extremidade deve poder enviar dados de maneira confiável. Ambas as partes precisam estabelecer um ISN, e ambas precisam reconhecer o ISN da outra.
Na verdade, o que você tem é exatamente a sua descrição do handshake de mão dupla, mas em cada direção . Portanto, quatro eventos ocorrendo. E, novamente, as duas bandeiras do meio acontecem no mesmo pacote. Como tal, três pacotes estão envolvidos em um processo completo de inicialização da conexão TCP.
O handshake de três vias é necessário porque ambas as partes precisam syn chronize seus números de sequência de segmentos utilizados durante a sua transmissão. Para isso, cada um deles envia (por sua vez) um segmento SYN com um número de sequência definida para um valor aleatório n , o qual é então ack nowledged pela outra parte, através de um segmento ACK com um número de sequência definida como n + 1 .
Eddie
o comentário de sua resposta.
Para que a conexão funcione, cada lado precisa verificar se pode enviar pacotes para o outro lado. A única maneira de garantir que você tenha um pacote para o outro lado é obtendo um pacote deles que, por definição, não teria sido enviado a menos que o pacote que você enviou passasse . O TCP basicamente usa dois tipos de mensagens para isso: SYN (para solicitar prova de que esse pacote foi aprovado) e ACK (que é enviado apenas após a conclusão de um SYN, para provar que o SYN foi aprovado). Na verdade, existe um terceiro tipo de mensagem, mas chegaremos a isso em um momento.
Antes de a conexão iniciar, nenhum dos lados realmente sabe algo sobre o outro. O cliente envia um pacote SYN para o servidor, para solicitar prova de que suas mensagens podem passar . Isso não diz nada a ninguém, mas é o primeiro passo do aperto de mão.
Se o SYN passar, o servidor saberá que o cliente pode enviar pacotes para ele, porque, bem, aconteceu. Mas isso não prova que o servidor possa enviar pacotes de volta: os clientes podem enviar SYNs por vários motivos . Portanto, o servidor precisa enviar duas mensagens de volta ao cliente: um ACK (para provar que o SYN foi aprovado) e um SYN (para solicitar um ACK próprio). O TCP combina essas duas mensagens em uma - uma mensagem SYN-ACK, se você desejar - para reduzir o tráfego de rede. Este é o segundo passo do aperto de mão.
Como um SYN-ACK é um ACK, o cliente agora tem certeza de que pode enviar pacotes para o servidor. E como um SYN-ACK é um SYN, ele também sabe que o servidor deseja uma prova de que essa mensagem foi recebida. Portanto, ele envia de volta um ACK: apenas um ACK simples desta vez, porque não precisa mais de provas de que seus pacotes podem passar. Esta é a etapa final do handshake: o cliente agora sabe que os pacotes podem ir nos dois sentidos e que o servidor está prestes a descobrir isso (porque sabe que o ACK será executado).
Depois que o ACK é concluído, agora o servidor sabe que pode enviar pacotes para o cliente . Ele também sabe que o cliente sabe disso, para que possa começar a enviar dados imediatamente. O aperto de mão está completo. Temos um bom canal.
Bem, a rigor, não podemos ter certeza de que temos um bom canal . Só porque essa sequência de pacotes passou não garante estritamente que outros o farão. Não podemos provar isso sem enviar um número infinito de SYNs e ACKs, e então nada mais seria feito; portanto, essa não é realmente uma opção prática. Mas, na prática, três etapas são boas o suficiente para a maioria dos propósitos .
Na verdade, um handshake de três vias não é o único meio de estabelecer uma conexão TCP. A troca simultânea de SYN também é permitida: http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-4.htm
Isso pode ser visto como um tipo de aperto de mão duplo.
A conexão TCP é bidirecional. O que isso significa é que, na verdade, é um par de conexões unidirecionais. O iniciador envia SYN, o respondente envia ACK: uma conexão simplex é iniciada. "Então" o respondente envia SYN, o iniciador envia ACK: outra conexão simplex é iniciada. Duas conexões simplex formam uma sessão TCP duplex, concorda? Então, logicamente, existem quatro etapas envolvidas; mas como os sinalizadores SYN e ACK são "campos" diferentes do cabeçalho TCP, eles podem ser definidos simultaneamente - a segunda e a terceira etapas (das quatro) são combinadas, portanto tecnicamente há três trocas de pacotes. Cada conexão simplex (meia) usa troca bidirecional, como você propôs.
Se o Servidor e o Cliente desejam criar uma conexão, eles precisam confirmar quatro coisas:
O cliente precisa confirmar que pode receber pacotes do servidor
O cliente precisa confirmar uma coisa: o servidor pode receber pacotes do cliente
Depois Client ------SYN-----> Server
, a regra 1 é confirmada.
Depois Client <---ACK/SYN---- Server
, as regras 2 e 3 são confirmadas.
Portanto, é necessário um terceiro pacote para confirmar a regra 4.
Não é necessário. É óbvio que uma mensagem curta deve exigir apenas um pacote para o servidor, que inclui a mensagem start +, e um pacote novamente reconhecendo-o.
As respostas anteriores apenas descrevem o sistema sem discutir a necessidade de números de sequência aleatórios etc., em primeiro lugar. A pergunta original era sobre o design do próprio TCP - obviamente, se você usar o protocolo TCP, precisará de três mensagens, porque esse é o protocolo. Mas por que o TCP foi projetado dessa maneira em primeiro lugar?
Acredito que a ideia original era que não havia distinção entre clientes e servidores. Ambos conheciam os portos do outro de maneira bidirecional e podiam iniciar a conversa. E isso exigia Syns etc.
Mas não é, claro, como é usado hoje. O servidor escuta em uma porta conhecida e faz e "aceita", o número da porta do cliente é efêmero. Eu nem acho que é possível para um servidor aguardando um "aceitar" enviar uma solicitação para outro no mesmo número de porta do cliente em sistemas operacionais normais.
(Observe que se trata de iniciação bidirecional da conexão, o que nunca é feito hoje. Isso é bem diferente de enviar mensagens bidirecionais para uma conexão estabelecida uma vez.)
Para contornar a ineficiência do TCP, usamos protocolos como o HTTP 1.1, que podem reutilizar a mesma conexão para várias solicitações e, assim, evitar o handshake do TCP que não era necessário em primeiro lugar.
Mas o HTTP 1.1 é relativamente novo. E o SSL / TLS precisava de uma maneira de reutilizar a sessão desde o início devido ao custo dos algoritmos da PKI. Portanto, esse protocolo inclui seu próprio mecanismo de reutilização de sessão, executado em cima do HTTP 1.1, que é executado em cima do TCP.
É assim com o software. Fudges em kludges que, quando combinados, produzem um resultado aceitável.
Depois de ler a resposta de Eddie (aceito como correto), ainda há dúvidas sobre o motivo pelo qual o primeiro host não pode atribuir ambos os ISNs com números aleatórios e o segundo apenas aceita. O verdadeiro motivo do uso do handshake de três vias é evitar meias conexões . Cenário de meia conexão no handshake bidirecional:
1) Cliente --- SYN -> Servidor
2) O cliente muda de idéia e não deseja mais se conectar
3) Cliente <-X-ACK-- Servidor // ACK foi perdido
O servidor não vê SYN reenviado, então ele acha que o cliente recebeu seu ACK e a conexão foi estabelecida. Como resultado, o servidor possui uma conexão que nunca será fechada