Настройка TCP-соединения
Когда мы просматриваем веб-страницы, отправляем электронные письма или играем в онлайн-игры, мы часто не задумываемся о сложной сетевой инфраструктуре, лежащей в её основе. Однако именно эти, казалось бы, незначительные шаги обеспечивают стабильную связь между нами и сервером. Одним из важнейших шагов является установление TCP-соединения, а его ядром является трёхстороннее рукопожатие.
В этой статье подробно рассматриваются принцип, процесс и значение трехстороннего рукопожатия. Шаг за шагом мы объясним, почему необходимо трехстороннее рукопожатие, как оно обеспечивает стабильность и надежность соединения, и насколько оно важно для передачи данных. Более глубокое понимание трехстороннего рукопожатия позволит нам лучше понять основные механизмы сетевой коммуникации и получить более четкое представление о надежности TCP-соединений.
Процесс трехстороннего рукопожатия TCP и переходы состояний
TCP — это транспортный протокол, ориентированный на установление соединения, который требует установления связи перед передачей данных. Процесс установления соединения осуществляется посредством трехстороннего рукопожатия.
Давайте подробнее рассмотрим TCP-пакеты, отправляемые в каждом соединении.
Изначально и клиент, и сервер находятся в состоянии CLOSED. Сначала сервер активно прослушивает порт и находится в состоянии LISTEN, что означает, что сервер необходимо запустить. Затем клиент готов начать доступ к веб-странице. Ему необходимо установить соединение с сервером. Формат первого пакета соединения следующий:
Когда клиент инициирует соединение, он генерирует случайный начальный порядковый номер (client_isn) и помещает его в поле "Порядковый номер" заголовка TCP. Одновременно клиент устанавливает флаг SYN в положение 1, чтобы указать, что исходящий пакет является пакетом SYN. Клиент указывает на свое желание установить соединение с сервером, отправляя первый пакет SYN на сервер. Этот пакет не содержит данных прикладного уровня (то есть, отправленных данных). На этом этапе статус клиента помечается как SYN-SENT.
Когда сервер получает SYN-пакет от клиента, он случайным образом инициализирует свой собственный серийный номер (server_isn), а затем помещает этот номер в поле «Серийный номер» заголовка TCP. Далее сервер вводит client_isn + 1 в поле «Номер подтверждения» и устанавливает биты SYN и ACK в 1. Наконец, сервер отправляет пакет клиенту, который не содержит данных прикладного уровня (и никаких данных для отправки сервером). В этот момент сервер находится в состоянии SYN-RCVD.
После получения пакета от сервера клиенту необходимо выполнить следующие оптимизации для ответа на итоговый пакет: Во-первых, клиент устанавливает бит ACK в заголовке TCP ответного пакета в 1; Во-вторых, клиент вводит значение server_isn + 1 в поле "Номер подтверждения ответа"; Наконец, клиент отправляет пакет на сервер. Этот пакет может передавать данные от клиента к серверу. После завершения этих операций клиент переходит в состояние ESTABLISHED.
После получения ответного пакета от клиента сервер также переходит в состояние ESTABLISHED.
Как видно из описанного выше процесса, при выполнении трехстороннего рукопожатия третий этап может передавать данные, а первые два — нет. Это часто задаваемый вопрос на собеседованиях. После завершения трехстороннего рукопожатия обе стороны переходят в состояние ESTABLISHED, указывающее на успешное установление соединения, после чего клиент и сервер могут начать обмениваться данными.
Почему три рукопожатия? Не два, а четыре?
Наиболее распространенный ответ: «Потому что трехстороннее рукопожатие гарантирует возможность приема и отправки». Этот ответ верен, но это лишь поверхностная причина, не раскрывающая основной смысл. Далее я проанализирую причины трехстороннего рукопожатия с трех точек зрения, чтобы углубить наше понимание этого вопроса.
Трехстороннее рукопожатие позволяет эффективно избежать инициализации ранее повторявшихся соединений (главная причина).
Трехстороннее рукопожатие гарантирует, что обе стороны получили надежный начальный порядковый номер.
Трехстороннее соглашение позволяет избежать нерационального использования ресурсов.
Причина 1: Избегать повторных объединений исторических файлов.
Вкратце, основная причина использования трёхстороннего рукопожатия заключается в предотвращении путаницы, вызванной повторной инициализацией старых соединений. В сложной сетевой среде передача пакетов данных не всегда осуществляется в соответствии с заданным временем, и старые пакеты данных могут поступать на целевой хост первыми из-за перегрузки сети и других причин. Чтобы избежать этого, TCP использует трёхстороннее рукопожатие для установления соединения.
Когда клиент отправляет несколько пакетов SYN для установления соединения подряд, например, в условиях перегрузки сети, могут произойти следующие события:
1. Старые SYN-пакеты поступают на сервер раньше, чем новые SYN-пакеты.
2. После получения старого пакета SYN сервер отправит клиенту ответный пакет SYN + ACK.
3. Когда клиент получает пакет SYN + ACK, он определяет, что это историческое соединение (истек порядковый номер или истекло время ожидания) в соответствии со своим собственным контекстом, а затем отправляет серверу пакет RST для прерывания соединения.
При двухэтапном рукопожатии невозможно определить, является ли текущее соединение историческим. Трехэтапное рукопожатие позволяет клиенту определить, является ли текущее соединение историческим, исходя из контекста, когда он готов отправить третий пакет:
1. Если это историческое соединение (истек порядковый номер или истекло время ожидания), пакет, отправленный третьим этапом рукопожатия, представляет собой пакет RST для прерывания исторического соединения.
2. Если это не историческое соединение, то пакет, отправленный в третий раз, является пакетом подтверждения (ACK), и обе взаимодействующие стороны успешно устанавливают соединение.
Таким образом, основная причина использования TCP трехстороннего рукопожатия заключается в том, что оно инициализирует соединение для предотвращения повторных подключений.
Причина 2: Для синхронизации начальных порядковых номеров обеих сторон.
Обе стороны протокола TCP должны поддерживать порядковый номер, который является ключевым фактором для обеспечения надежной передачи. Порядковые номера играют важную роль в TCP-соединениях. Они выполняют следующие функции:
Приёмник может исключить дублирующиеся данные и обеспечить их точность.
Для обеспечения целостности данных приемник может принимать пакеты в порядке их порядковых номеров.
● Порядковый номер позволяет идентифицировать пакет данных, полученный другой стороной, обеспечивая надежную передачу данных.
Таким образом, после установления TCP-соединения клиент отправляет SYN-пакеты с начальным порядковым номером и требует от сервера ответа в виде ACK-пакета, подтверждающего успешное получение SYN-пакета от клиента. Затем сервер отправляет SYN-пакет с начальным порядковым номером клиенту и ожидает окончательного ответа от клиента, чтобы обеспечить надежную синхронизацию начальных порядковых номеров.
Хотя четырехэтапное рукопожатие также позволяет надежно синхронизировать начальные порядковые номера обеих сторон, второй и третий этапы можно объединить в один, в результате чего получится трехэтапное рукопожатие. Однако два этапа рукопожатия гарантируют лишь успешное получение начального порядкового номера одной стороны другой стороной, но не гарантируют подтверждения начальных порядковых номеров обеих сторон. Поэтому трехэтапное рукопожатие является наилучшим вариантом для обеспечения стабильности и надежности TCP-соединений.
Причина 3: Избегать растраты ресурсов.
Если происходит только «двухэтапное подтверждение», и запрос SYN от клиента блокируется в сети, клиент не может получить пакет ACK, отправленный сервером, поэтому SYN будет отправлен повторно. Однако, поскольку третьего этапа подтверждения нет, сервер не может определить, получил ли клиент подтверждение ACK для установления соединения. Следовательно, сервер может устанавливать соединение только после получения каждого запроса SYN. Это приводит к следующему:
Расточительство ресурсов: Если SYN-запрос клиента блокируется, что приводит к повторной передаче нескольких SYN-пакетов, сервер после получения запроса установит несколько избыточных недействительных соединений. Это приводит к ненужному расходованию серверных ресурсов.
Сохранение сообщений: Из-за отсутствия третьего подтверждения (ACK) сервер не может определить, правильно ли клиент получил подтверждение ACK для установления соединения. В результате, если сообщения застревают в сети, клиент будет постоянно отправлять SYN-запросы, что приведет к постоянному установлению новых соединений сервером. Это увеличит перегрузку сети и задержки, а также негативно повлияет на общую производительность сети.
Поэтому для обеспечения стабильности и надежности сетевого соединения протокол TCP использует трехэтапное рукопожатие для установления связи, чтобы избежать возникновения подобных проблем.
Краткое содержание
ОнБрокер сетевых пакетовУстановление TCP-соединения осуществляется посредством трехстороннего рукопожатия. В ходе трехстороннего рукопожатия клиент сначала отправляет серверу пакет с флагом SYN, указывая на желание установить соединение. После получения запроса от клиента сервер отправляет клиенту ответный пакет с флагами SYN и ACK, указывая на то, что запрос на соединение принят, и отправляет свой собственный начальный порядковый номер. Наконец, клиент отправляет серверу ответ с флагом ACK, указывающий на успешное установление соединения. Таким образом, обе стороны находятся в состоянии ESTABLISHED и могут начать обмениваться данными друг с другом.
В целом, процесс трехстороннего рукопожатия при установлении TCP-соединения призван обеспечить стабильность и надежность соединения, избежать путаницы и нерационального использования ресурсов при работе с предыдущими соединениями, а также гарантировать, что обе стороны смогут получать и отправлять данные.
Дата публикации: 08.01.2025






