KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программное обеспечение » Уильям Стивенс - UNIX: разработка сетевых приложений

Уильям Стивенс - UNIX: разработка сетевых приложений

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Уильям Стивенс, "UNIX: разработка сетевых приложений" бесплатно, без регистрации.
Перейти на страницу:

Рис. 2.4. Диаграмма состояний TCP

Для соединения определено 11 различных состояний, а правила TCP предписывают переходы от одного состояния к другому в зависимости от текущего состояния и сегмента, полученного в этом состоянии. Например, если приложение выполняет активное открытие в состоянии CLOSED (Закрыло), TCP отправляет сегмент SYN, и новым состоянием становится SYN_SENT (Отправлен SYN). Если затем TCP получает сегмент SYN с сегментом ACK, он отправляет сегмент ACK, и следующим состоянием становится ESTABLISHED (Соединение установлено). В этом последнем состоянии проходит большая часть обмена данными.

Две стрелки, идущие от состояния ESTABLISHED, относятся к разрыву соединения. Если приложение вызывает функцию close перед получением признака конца файла (активное закрытие), происходит переход к состоянию FIN_WAIT_1 (Ожидание FIN 1). Но если приложение получает сегмент FIN в состоянии ESTABLISHED (пассивное закрытие), происходит переход в состояние CLOSE_WAIT (Ожидание закрытия).

Мы отмечаем нормальные переходы клиента с помощью более толстой сплошной линии, а нормальные переходы сервера — с помощью штриховой линии. Мы также должны отметить, что существуют два перехода, о которых мы не говорили: одновременное открытие (когда оба конца связи отправляют сегменты SYN приблизительно в одно время, и эти сегменты пересекаются в сети) и одновременное закрытие (когда оба конца связи отправляют сегменты FIN). В главе 18 [111] содержатся примеры и описания обоих этих сценариев, которые хотя и возможны, но встречаются достаточно редко.

Одна из причин, по которым мы приводим здесь диаграмму перехода состояний, — мы хотим показать все 11 состояний TCP и их названия. Эти состояния отображаются программой netstat, которая является полезным средством отладки клиент-серверных приложений. Мы будем использовать программу netstat для отслеживания изменений состояния в главе 5.

Обмен пакетами

На рис. 2.5 представлен реальный обмен пакетами, происходящий во время соединения TCP: установление соединения, передача данных и завершение соединения. Мы также показываем состояния TCP, через которые проходит каждый узел.

Рис. 2.5. Обмен пакетами для соединения TCP

В этом примере клиент объявляет размер сегмента (MSS) равным 536 байт (это означает, что его реализация работает с минимальным размером буфера сборки пакетов), а сервер — 1460 байт (типичное значение для IPv4 в Ethernet). Как видно, MSS в каждом направлении передачи вполне могут отличаться (см. также упражнение 2.5).

Как только соединение установлено, клиент формирует запрос и посылает его серверу. Мы считаем, что этот запрос соответствует одиночному сегменту TCP (то есть его размер меньше 1460 байт — анонсированного размера MSS сервера). Сервер обрабатывает запрос и отправляет ответ, и мы также считаем, что ответ соответствует одиночному сегменту (в данном примере меньше 536 байт). Оба сегмента данных мы отобразили более жирными линиями. Заметьте, что подтверждение запроса клиента отправляется с ответом сервера. Это называется вложенным подтверждением (piggybacking) и обычно происходит, когда сервер успевает обработать запрос и подготовить ответ меньше, чем за 200 мс или около того. Если серверу требуется больше времени, скажем, 1 с, ответ будет приходить после подтверждения. (Динамика потока данных TCP подробно описана в главах 19 и 20 [111].)

Затем мы показываем четыре сегмента, закрывающих соединение. Заметьте, что узел, выполняющий активное закрытие (в данном сценарии клиент), входит в состояние TIME_WAIT. Мы рассмотрим это в следующем разделе.

На рис. 2.5 важно отметить, что если целью данного соединения было отправить запрос, занимающий один сегмент, и получить ответ, также занимающий один сегмент, то при использовании TCP всего будет задействовано восемь сегментов. Если же используется UDP, произойдет обмен только двумя сегментами: запрос и ответ. Но при переходе от TCP к UDP теряется надежность, которую TCP предоставляет приложению, и множество задач по обеспечению надежности транспортировки данных переходит с транспортного уровня (TCP) на уровень приложения. Другое важное свойство, предоставляемое TCP, — это управление в условиях перегрузки, которое в случае использования протокола UDP должно принимать на себя приложение. Тем не менее важно понимать, что многие приложения используют именно UDP, потому что они обмениваются небольшими объемами данных, a UDP позволяет избежать накладных расходов, возникающих при установлении и разрыве соединения TCP.

2.7. Состояние TIME_WAIT

Без сомнений, самым сложным для понимания аспектом TCP в отношении сетевого программирования является состояние TIME_WAIT (время ожидания). На рис. 2.4 мы видим, что узел, выполняющий активное закрытие, проходит это состояние. Продолжительность этого состояния равна двум MSL (maximum segment lifetime — максимальное время жизни сегмента), иногда этот период называется 2MSL.

В каждой реализации TCP выбирается какое-то значение MSL. Рекомендуемое значение, приведенное в документе RFC 1122 [10], равно 2 мин, хотя Беркли-реализации традиционно использовали значение 30 с. Это означает, что продолжительность состояния TIME_WAIT — от 1 до 4 мин. MSL — это максимальное количество времени, в течение которого дейтаграмма IP может оставаться в сети. Это время ограничено, поскольку каждая дейтаграмма содержит 8-разрядное поле предельного количества прыжков (hop limit) (поле TTL IPv4 на рис. А.1 и поле «Предельное количество транзитных узлов» IPv6 на рис. А.2), максимальное значение которого равно 255. Хотя этот предел ограничивает количество транзитных узлов, а не время пребывания пакета в сети, считается, что пакет с максимальным значением этого предела (которое равно 255) не может существовать в сети более MSL секунд.

Пакеты в объединенных сетях обычно теряются в результате различных аномалий. Маршрутизатор отключается, или нарушается связь между двумя маршрутизаторами, и им требуются секунды или минуты для стабилизации и нахождения альтернативного пути. В течение этого периода времени могут возникать петли маршрутизации (маршрутизатор А отправляет пакеты маршрутизатору В, а маршрутизатор В отправляет их обратно маршрутизатору А), и пакеты теряются в этих петлях. В этот момент, если потерянный пакет — это сегмент TCP, истекает установленное время ожидания отправляющего узла, и он снова передает пакет, и этот заново переданный пакет доходит до конечного места назначения по некоему альтернативному пути. Но если спустя некоторое время (не превосходящее количества секунд MSL после начала передачи потерянного пакета) петля маршрутизации исправляется, пакет, потерянный в петле, отправляется к конечному месту назначения. Начальный пакет называется потерянной копией или дубликатом (lost duplicate), а также блуждающей копией или дубликатом (wandering duplicate). TCP должен обрабатывать эти дублированные пакеты.

Есть две причины существования состояния TIME_WAIT:

■ необходимо обеспечить надежность разрыва двустороннего соединения TCP;

■ необходимо подождать, когда истечет время жизни в сети старых дублированных сегментов.

Первую причину можно объяснить, рассматривая рис. 2.5 в предположении, что последний сегмент ACK потерян. Сервер еще раз отправит свой последний сегмент FIN, поэтому клиент должен сохранять информацию о своем состоянии, чтобы отправить завершающее подтверждение ACK повторно. Если бы клиент не сохранял информацию о состоянии, он ответил бы серверу сегментом RST (еще один вид сегмента TCP), что сервер интерпретировал бы как ошибку. Если ответственность за корректное завершение двустороннего соединения в обоих направлениях ложится на TCP, он должен правильно обрабатывать потерю любого из четырех сегментов. Этот пример объясняет, почему в состоянии TIME_WAIT остается узел, выполняющий активное закрытие: именно этому узлу может потребоваться повторно передать подтверждение.

Чтобы понять вторую причину, по которой необходимо состояние TIME_WAIT, давайте считать, что у нас имеется соединение между IP-адресом 12.106.32.254, порт 1500 и IP-адресом 206.168.112.219, порт 21. Это соединение закрывается, и спустя некоторое время мы устанавливаем другое соединение между теми же IP-адресами и портами: 12.106.32.254, порт 1500 и 206.168.112.219, порт 21. Последнее соединение называется новым воплощением (incarnation) предыдущего соединения, поскольку IP-адреса и порты те же. TCP должен предотвратить появление старых дубликатов, относящихся к данному соединению, в новом воплощении этого соединения. Чтобы гарантировать это, TCP запрещает установление нового воплощения соединения, которое в данный момент находится в состоянии TIME_WAIT. Поскольку продолжительность состояния TIME_WAIT равна двум MSL, это позволяет удостовериться, что истечет и время жизни пакетов, посланных в одном направлении, и время жизни пакетов, посланных в ответ. Используя это правило, мы гарантируем, что в момент успешного установления соединения TCP время жизни в сети всех старых дубликатов от предыдущих воплощений этого соединения уже истекло.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*