📚 Hub Books: Онлайн-чтение книгРазная литератураКомпьютерные сети. 6-е изд. - Эндрю Таненбаум

Компьютерные сети. 6-е изд. - Эндрю Таненбаум

Шрифт:

-
+

Интервал:

-
+
1 ... 205 206 207 208 209 210 211 212 213 ... 335
Перейти на страницу:
контроле перегрузки мы поговорим в разделе 6.5.10.

6.5.5. Установка TCP-соединения

В TCP соединения устанавливаются с помощью «тройного рукопожатия», как было описано в разделе 6.2.2. Чтобы создать соединение, одна сторона (например, сервер) пассивно ожидает входящего соединения, выполняя примитивы LISTEN и ACCEPT с указанием конкретного источника либо без него.

Другая сторона (например, клиент) выполняет примитив CONNECT, сообщая IP-адрес и порт, с которым она хочет установить соединение, максимальный размер TCP-сегмента, который она может принять, и, по желанию, некоторые данные пользователя (например, пароль). CONNECT отправляет TCP-сегмент с установленным битом SYN и сброшенным битом ACK и ждет ответа от другой стороны.

Когда этот сегмент приходит по назначению, TCP-подсистема проверяет, выполнил ли какой-нибудь процесс примитив LISTEN, указав в качестве параметра тот же порт, который содержится в поле Destination port. Если такого процесса нет, она отвечает отправкой сегмента с установленным битом RST для отказа от соединения.

Если какой-то процесс прослушивает указанный порт, то TCP-сегмент передается этому процессу. Он может принять соединение или отказаться от него. Если процесс принимает соединение, он отвечает подтверждением. Последовательность TCP-сегментов, отправляемых в обычном случае, показана на илл. 6.37 (а). Обратите внимание, что сегмент с установленным битом SYN занимает 1 байт пространства порядковых номеров, что позволяет избежать неоднозначности в их подтверждениях.

Илл. 6.37. (а) Установка TCP-соединения в обычном случае. (б) Одновременная установка соединения обеими сторонами

Когда два хоста одновременно пытаются установить соединение друг с другом, то события происходят в иной последовательности (см. илл. 6.37 (б)). В результате будет установлено только одно соединение, а не два, так как соединения идентифицируются по паре конечных точек. То есть если они оба обозначают себя с помощью пары (x, y), делается всего одна табличная запись (x, y).

Начальное значение порядкового номера, выбранное каждым хостом, должно медленно меняться, а не равняться константе (например, нулю). Как мы уже говорили в разделе 6.2.2, это правило обеспечивает защиту от задержавшихся копий пакетов. Изначально эта схема была реализована с помощью таймера, изменяющего свое состояние каждые 4 мкс.

Однако проблема реализации схемы «тройного рукопожатия» состоит в том, что слушающий процесс должен помнить свой порядковый номер до тех пор, пока он не отправит собственный SYN-сегмент. Это значит, что злонамеренный отправитель может блокировать ресурсы хоста, отправляя на него поток SYN-сегментов и не разрывая соединение. Такие атаки называются лавинной адресацией SYN-сегментов (SYN flood). В 1990-е годы многие веб-серверы оказались парализованными из-за них. Сегодня уже существуют методы защиты от таких атак.

В частности, для защиты от них можно использовать метод под названием SYN cookies. Вместо того чтобы запоминать порядковый номер, хост генерирует криптографическое значение номера, записывает его в исходящий сегмент и забывает. Если «тройное рукопожатие» завершается, этот номер (увеличенный на единицу) вернется на хост. Хост может повторно сгенерировать правильный порядковый номер, вычислив значение той же криптографической функции, при условии, что известны входные данные (это может быть IP-адрес и порт другого хоста, а также какое-то секретное значение). С помощью этой процедуры хост может проверять правильность подтвержденного порядкового номера, не запоминая его. Одна из тонкостей этого метода состоит в том, что он не работает с дополнительными параметрами TCP. Поэтому SYN cookies можно использовать только в случае лавинной адресации SYN-сегментов. Но в целом это очень интересный прием. Более подробно см. RFC 4987 и работу Лемона (Lemon, 2002).

6.5.6. Разрыв TCP-соединения

Хотя TCP-соединения полнодуплексные, чтобы понять, как происходит их разъединение, лучше считать их парами симплексных соединений. Каждое симплексное соединение разрывается независимо от своего напарника. Чтобы его разорвать, любая из сторон может отправить TCP-сегмент с установленным битом FIN; это означает, что у него больше нет данных для передачи. После подтверждения TCP-сегмента это направление закрывается. Тем не менее данные могут продолжать передаваться неопределенно долго в противоположную сторону. Соединение разрывается, когда закрываются оба направления. Обычно для разрыва требуются четыре TCP-сегмента: по одному с битом FIN и по одному с битом ACK в каждом направлении. Первый бит ACK и второй бит FIN могут также содержаться в одном TCP-сегменте, что уменьшит количество сегментов до трех.

Как при телефонном разговоре, когда оба участника могут одновременно попрощаться и повесить трубку, оба конца TCP-соединения могут отправить FIN-сегменты в одно и то же время. Они оба получают обычные подтверждения, и соединение закрывается. По сути, между одновременным и последовательным разъединением нет никакой разницы.

Чтобы избежать проблемы «двух армий» (см. раздел 6.2.3), используются таймеры. Если ответ на отправленный FIN-сегмент не приходит в течение двух максимальных интервалов времени жизни пакета, отправитель FIN-сегмента разрывает соединение. Другая сторона в конце концов заметит, что ей никто не отвечает, и также отсоединится. Эта схема несовершенна, однако, учитывая недостижимость идеала, приходится пользоваться тем, что есть. На практике проблемы возникают довольно редко.

6.5.7. Модель управления TCP-соединением

Этапы, необходимые для установления и разрыва соединения, могут быть представлены в виде модели конечного автомата, 11 состояний которого перечислены на илл. 6.38. В каждом из этих состояний разрешены определенные события, в ответ на которые могут осуществляться действия. При возникновении каких-либо других событий сообщается об ошибке.

Каждое соединение начинается в состоянии CLOSED (закрыто). Оно может покинуть это состояние, предпринимая либо активную (CONNECT), либо пассивную (LISTEN) попытку открыть соединение. Если другая сторона осуществляет противоположное действие, соединение устанавливается и переходит в состояние ESTABLISHED. Инициатором разрыва соединения может выступить любая сторона. По завершении этого процесса соединение возвращается в состояние CLOSED.

Состояние

Описание

CLOSED

Закрыто. Соединение не является активным и не находится в процессе установления

LISTEN

Ожидание. Сервер ожидает входящего запроса

SYN RCVD

Прибыл запрос соединения. Ожидание подтверждения

SYN SENT

Запрос соединения отправлен. Приложение начало открывать соединение

ESTABLISHED

Установлено. Нормальное состояние передачи данных

FIN WAIT 1

Приложение сообщило, что ему больше нечего передавать

FIN WAIT 2

Другая сторона согласна разорвать соединение

TIME WAIT

Ожидание, пока из сети не исчезнут все пакеты

CLOSING

Обе стороны попытались одновременно закрыть соединение

CLOSE WAIT

Другая сторона инициировала разъединение

LAST ACK

Ожидание, пока из сети не исчезнут все пакеты

Илл. 6.38. Состояния конечного автомата, управляющего TCP-соединением

Конечный автомат показан на илл. 6.39. Типичный случай клиента, активно соединяющегося с пассивным сервером, показан жирными линиями — сплошными для клиента и пунктирными для сервера. Тонкие линии обозначают необычные последовательности событий. Каждая линия на илл. 6.39 маркирована парой событие/действие. Событие может представлять собой либо обращение пользователя к системной процедуре (CONNECT, LISTEN, SEND или CLOSE), либо прибытие сегмента (SYN, FIN,

1 ... 205 206 207 208 209 210 211 212 213 ... 335
Перейти на страницу:

Комментарии

Обратите внимание, что комментарий должен быть не короче 20 символов. Покажите уважение к себе и другим пользователям!

Никто еще не прокомментировал. Хотите быть первым, кто выскажется?