TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security)
Шрифт:
Способность управлять тем, как посылает данные другая сторона, является важным свойством, обеспечивающим масштабируемость TCP/IP.
На рис. 10.8 показан пример сценария соединения. Представлены очень простые начальные порядковые номера, чтобы не перегружать рисунок. Отметим, что на данном рисунке клиент способен получать большие по размеру сегменты, чем сервер.
Рис. 10.8. Установление соединения
Выполняются следующие операции:
1. Сервер инициализируется
2. Клиент запрашивает у TCP открытие соединения с сервером по указанному IP-адресу и порту (это состояние называется активным открытием — active open).
3. Клиентская TCP получает начальный порядковый номер (в данном примере — 1000) и посылает сегмент синхронизации (synchronize segment — SYN). В этом сегменте пересылается порядковый номер, размер приемного окна (4 К) и размер наибольшего сегмента, который может принять клиент (1460 байт).
4. Когда поступает SYN, серверная TCP получает свой начальный порядковый номер (3000). Она посылает сегмент SYN, содержащий начальный порядковый номер (3000), ACK 1001 (что означает нумерацию первого посланного клиентом байта как 1001), размер приемного окна (4 К) и размер наибольшего сегмента, который сможет получить сервер (1024 байта).
5. Клиентская TCP, получив от сервера сообщение SYN/ACK, отсылает обратно ACK 3001 (первый байт посланных сервером данных должен нумероваться как 3001).
6. Клиентская TCP указывает своему приложению на открытие соединения.
7. Серверная TCP, получив от клиентской TCP сообщение ACK, информирует свое приложение об открытии соединения.
Клиент и сервер анонсируют свои правила для принимаемых данных, синхронизируют свои порядковые номера и становятся готовыми к обмену данными. Спецификация TCP разрешает и другой сценарий (не слишком удачный), когда равные между собой приложения одновременно выполняют активное открытие друг друга.
10.4.2 Установка значений параметров IP
Запрос приложения на установку соединения может заодно указать параметры для датаграмм IP, которые будут переносить данные этого соединения. Если не указывается определенное значение параметра, используется величина, заданная по умолчанию.
Например, приложение может выбрать требуемое значение для приоритета IP или типа обслуживания. Поскольку каждая из соединяемых сторон независимо друг от друга устанавливает собственный приоритет и тип обслуживания, теоретически эти значения могут отличаться для различных направлений потоков данных. Как правило, на практике применяются одинаковые значения для каждого направления обмена.
Когда в приложении задействованы варианты безопасности для правительственных или военных учреждений, каждая из конечных точек соединения должна использовать одинаковые уровни безопасности, иначе такое соединение не будет установлено.
10.5 Пересылка данных
Пересылка данных начинается после завершения трехшагового подтверждения создания соединения (см. рис. 10.9). Стандарт TCP позволяет включать в сегменты подтверждения обычные данные, но они не будут доставляться приложению, пока создание соединения не завершится. Для упрощения нумерации применяются 1000-байтные сообщения. Каждый сегмент заголовка TCP имеет поле ACK, идентифицирующее порядковый номер байта, который предполагается получить от партнера по соединению.
Рис. 10.9. Простой поток обмене данными и ACK
Первый посланный клиентом сегмент содержит байты от 1001 до 2000. В его поле ACK должно находиться значение 3001, что указывает порядковый номер байта, который предполагается получить от сервера.
Сервер отвечает клиенту сегментом, содержащим 1000 байт данных (начинающихся с номера 3001). В его поле ACK заголовка TCP будет указано, что байты с 1001 по 2000 уже успешно получены, поэтому следующий ожидающийся от клиента порядковый номер сегмента должен быть 2001.
Далее клиент посылает сегменты, начинающиеся с байтов 2001, 3001 и 4001 в указанной последовательности. Отметим, что клиент не ожидает ACK после каждого из посланных сегментов. Данные пересылаются партнеру до заполнения его буферного пространства (ниже мы увидим, что получатель может очень точно указать объем пересылаемых ему данных).
Сервер экономит пропускную способность соединения, используя единственный ACK для указания успешности пересылки всех сегментов.
На рис. 10.10 показана пересылка данных при потере первого сегмента. По завершении тайм-аута пересылка сегмента повторяется. Отметим, что, получив потерянный сегмент, приемник отправляет один ACK, подтверждающий пересылку обоих сегментов.
Рис. 10.10. Потеря данных и повторная трансляция
10.6 Закрытие соединения
Нормальное завершение соединения выполняется с помощью той же процедуры тройного рукопожатия, что и при открытии соединения. Каждая из сторон может начать закрытие соединения по следующему сценарию:
A: "Я закончил работу. Данных для пересылки больше нет".
B: "Хорошо".
В: "Я тоже завершил работу".
A: "Хорошо".
Допустим и такой сценарий (хотя он используется крайне редко):
A: "Я закончил работу. Данных для пересылки больше нет".
В: "Хорошо. Однако есть какие-то данные…"
В: "Я тоже завершил работу".
A: "Хорошо".
В рассмотренном ниже примере соединение закрывает сервер, как это часто происходит для связей клиент/сервер. В данном случае после ввода пользователем в сеансе telnet команды logout (выйти из системы) сервер инициирует запрос на закрытие соединения. В ситуации, показанной на рис. 10.11, выполняются следующие действия:
1. Приложение на сервере указывает TCP на закрытие соединения.
2. TCP сервера посылает заключительный сегмент (Final Segment — FIN), информируя своего партнера о том, что данных для отправки больше нет.
3. TCP клиента посылает ACK в сегменте FIN.
4. TCP клиента сообщает своему приложению, что сервер хочет закрыть соединение.
5. Клиентское приложение сообщает своему TCP о закрытии соединения.
6. TCP клиента посылает сообщение FIN.
7. TCP сервера получает FIN от клиента и отвечает на него сообщением ACK.