Трехстороннее рукопожатие TCP работает так:
Client ------SYN-----> Server
Client <---ACK/SYN---- Server
Client ------ACK-----> Server
Почему не только это?
Client ------SYN-----> Server
Client <-----ACK------ Server
Трехстороннее рукопожатие TCP работает так:
Client ------SYN-----> Server
Client <---ACK/SYN---- Server
Client ------ACK-----> Server
Почему не только это?
Client ------SYN-----> Server
Client <-----ACK------ Server
Ответы:
Разбейте рукопожатие на то, что оно действительно делает.
В TCP две стороны отслеживают то, что они отправили, используя порядковый номер. По сути, это заканчивается тем, что все количество отправленных байтов было запущено. Принимающая сторона может использовать порядковый номер противоположного говорящего для подтверждения того, что она получила.
Но порядковый номер не начинается с 0. Он начинается с ISN (начальный порядковый номер), который является случайно выбранным значением. А поскольку TCP является двунаправленной связью, обе стороны могут «говорить», и поэтому обе стороны должны случайным образом генерировать ISN в качестве своего начального порядкового номера. Это, в свою очередь, означает, что обе стороны должны уведомить другую сторону о своем начальном ISN.
Таким образом, вы получите следующую последовательность событий для начала TCP-диалога между Алисой и Бобом:
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]
Обратите внимание, что происходят четыре события:
В действительности, два средних события (# 2 и # 3) происходят в одном пакете. То, что делает пакет a SYN
или ACK
просто представляет собой двоичный флаг, включается или выключается внутри каждого заголовка TCP , поэтому ничто не мешает включить оба этих флага в одном пакете. Таким образом, трехстороннее рукопожатие заканчивается тем, что:
Bob <--- Alice SYN
Bob ---> Alice SYN ACK
Bob <--- Alice ACK
Обратите внимание на два экземпляра «SYN» и «ACK», по одному в каждом направлении.
Итак, чтобы вернуться к вашему вопросу, почему бы просто не использовать двустороннее рукопожатие? Короткий ответ заключается в том, что двустороннее рукопожатие позволило бы только одной стороне установить ISN, а другой стороне - подтвердить это. Это означает, что только одна сторона может отправлять данные.
Но TCP - это двунаправленный протокол связи, который означает, что любой конец должен иметь возможность надежно отправлять данные. Обе стороны должны установить ISN, и обе стороны должны признать ISN другой.
По сути, у вас есть именно ваше описание двустороннего рукопожатия, но в каждом направлении . Следовательно, четыре события происходят. И снова два средних флага находятся в одном пакете. Таким образом, три пакета участвуют в полном процессе инициации TCP-соединения.
Трехэтапного необходимо потому , что обе стороны должны син chronize их порядковые номера сегментов , используемых в процессе их передачи. Для этого, каждый из них посылает (в свою очередь) сегмент SYN с порядковым номером , установленным на случайной величины п , которая затем извед nowledged другой стороной через сегмент ACK с номером последовательности , установленным на N + 1 .
Eddie
комментарий к своему ответу.
Чтобы соединение работало, каждая сторона должна убедиться, что она может отправлять пакеты другой стороне. Единственный способ убедиться, что вы получили пакет на другую сторону, - это получить от него пакет, который по определению не был бы отправлен, если бы пакет, который вы отправили, не прошел . TCP по существу использует два вида сообщений для этого: SYN (для запроса подтверждения, что этот пакет прошел) и ACK (который отправляется только после того, как проходит SYN, чтобы доказать, что SYN прошел). На самом деле есть третий вид сообщения, но мы вернемся к этому через минуту.
До начала соединения ни одна из сторон ничего не знает о другой. Клиент отправляет пакет SYN на сервер, чтобы запросить подтверждение того, что его сообщения могут пройти . Это никому ничего не говорит, но это первый шаг рукопожатия.
Если SYN проходит, то сервер знает, что клиент может отправлять ему пакеты, потому что, ну, это просто произошло. Но это не доказывает, что сервер может отправлять пакеты обратно: клиенты могут отправлять SYN по многим причинам . Таким образом, сервер должен отправить клиенту два сообщения: ACK (чтобы доказать, что SYN прошел) и SYN (чтобы запросить собственный ACK). TCP объединяет эти два сообщения в одно сообщение SYN-ACK, если хотите, чтобы уменьшить сетевой трафик. Это второй шаг рукопожатия.
Поскольку SYN-ACK является ACK, клиент теперь точно знает, что он может отправлять пакеты на сервер. И поскольку SYN-ACK является SYN, он также знает, что серверу нужны доказательства того, что это сообщение получено. Таким образом, он отправляет обратно ACK: на этот раз просто ACK, потому что ему больше не нужно доказательство того, что его пакеты могут пройти. Это последний шаг рукопожатия: клиент теперь знает, что пакеты могут идти обоими путями, и что сервер только что выяснит это (потому что он знает, что ACK пройдет).
Как только этот ACK проходит, сервер знает, что он может отправлять пакеты клиенту . Он также знает, что клиент знает это, поэтому он может начать отправку данных прямо сейчас. Рукопожатие завершено. У нас хороший канал.
Ну, строго говоря, мы не можем быть уверены, что у нас есть хороший канал . Просто потому , что эта последовательность пакетов прошли через не строго гарантировать , что другие будут. Мы не можем доказать это, не отправив бесконечное количество SYN и ACK, и тогда больше ничего не будет сделано, так что это не очень практичный вариант. Но на практике три шага оказывается достаточным для большинства целей .
На самом деле, трехстороннее рукопожатие - не единственное средство установления TCP-соединения. Одновременный обмен SYN также разрешен: http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-4.htm
Это можно рассматривать как своего рода двойное рукопожатие.
TCP-соединение является двунаправленным. Это означает, что на самом деле это пара односторонних соединений. Инициатор отправляет SYN, ответчик отправляет ACK: начинается одно симплексное соединение. «Затем» ответчик отправляет SYN, инициатор отправляет ACK: начинается другое симплексное соединение. Два симплексных соединения образуют один дуплексный сеанс TCP, согласны? Таким образом, логически, есть четыре шага; но поскольку флаги SYN и ACK являются разными «полями» заголовка TCP, их можно устанавливать одновременно - второй и третий этапы (из четырех) объединяются, поэтому технически существует три обмена пакетами. Каждое симплексное (половинное) соединение использует двусторонний обмен, как вы предложили.
Если Сервер и Клиент хотят создать соединение, они должны подтвердить четыре вещи:
Клиент должен подтвердить, что он может получить пакет от Сервера
Клиенту нужно подтвердить вещь: сервер может получить пакет от клиента
После Client ------SYN-----> Server
этого правило 1 подтверждается.
После Client <---ACK/SYN---- Server
этого правила 2 и 3 подтверждаются.
Итак, для подтверждения правила 4 нужен третий пакет.
Это совсем не обязательно. Очевидно, что короткое сообщение должно требовать только один пакет для сервера, который включает в себя сообщение start +, и один пакет для его подтверждения.
Предыдущие ответы просто описывают систему, не обсуждая необходимость случайных порядковых номеров и т. Д. В первую очередь. Первоначальный вопрос был о структуре самого TCP - очевидно, если вы используете протокол TCP, тогда вам нужно три сообщения, потому что это протокол. Но почему TCP был спроектирован таким образом?
Я считаю, что первоначальная идея заключалась в том, что не было никакого различия между клиентами и серверами. Оба знали порты другого в двух направлениях, и любой из них мог начать разговор. И это требует Syns и т. Д.
Но это, конечно, не так, как сегодня. Сервер прослушивает общеизвестный порт и принимает и «принимает», номер порта клиента эфемерен. Я даже не думаю, что сервер, ожидающий «принять», может отправить запрос другому на тот же номер порта клиента в обычных операционных системах.
(Обратите внимание, что речь идет о двунаправленной инициализации соединения, что никогда не делается сегодня. Это сильно отличается от отправки двунаправленных сообщений по установившемуся соединению.)
Чтобы обойти неэффективность TCP, мы используем протоколы, такие как HTTP 1.1, которые могут повторно использовать одно и то же соединение для нескольких запросов и, таким образом, избежать рукопожатия TCP, который не был необходим в первую очередь.
Но http 1.1 является относительно новым. А для SSL / TLS требовался способ повторного использования сеанса с самого начала из-за стоимости алгоритмов PKI. Таким образом, этот протокол включает в себя собственный механизм повторного использования сеанса, который работает поверх Http 1.1, который работает поверх TCP.
Таков способ с программным обеспечением. Помадки на кладжах, которые в сочетании дают приемлемый результат.
После прочтения ответа Эдди (принятого как правильного), все еще остается вопрос, почему 1-й хост не может назначить оба ISN со случайными числами, а 2-й просто принимает его. Реальная причина использования трехстороннего рукопожатия - избегать полусоединений . Сценарий половины соединения в двухстороннем рукопожатии:
1) Клиент --- SYN -> Сервер
2) Клиент передумал и больше не хочет подключаться
3) Клиент <-X-ACK-- Сервер // ACK был потерян
Сервер не видит повторно отправленный SYN, поэтому он думает, что клиент получил свой ACK и соединение установлено. В результате сервер имеет соединение, которое никогда не будет закрыто