По сути, благодаря наличию транспортного уровня транспортный сервис может быть более надежным, чем лежащая ниже сеть. Более того, базовые операции транспортного сервиса могут быть разработаны таким образом, что они будут независимы от базовых операций сетевого сервиса, которые могут значительно варьироваться от сети к сети (например, сервис Ethernet без установления соединения может значительно отличаться от сервиса сети WiMAX с установлением соединения). Если спрятать сетевой сервис за набором базовых операций транспортного сервиса, то для изменения сетевого сервиса потребуется просто заменить один набор библиотечных процедур другими, делающими то же самое, но c помощью других сервисов более низкого уровня.
Благодаря наличию транспортного уровня прикладные программы могут использовать стандартный набор базовых операций и сохранять работоспособность в самых различных сетях. Им не придется учитывать имеющееся разнообразие интерфейсов сетей и уровней надежности. Если бы все реальные сети работали идеально и у всех сетей был один набор базовых операций, который гарантированно никогда не мог бы быть изменен, то транспортный уровень, вероятно, был бы не нужен. Однако в реальном мире он выполняет ключевую роль изолирования верхних уровней от деталей технологии, устройства и несовершенства сети.
Именно по этой причине часто проводится разграничение между уровнями с первого по четвертый и уровнями выше четвертого. Нижние четыре уровня можно рассматривать как поставщика транспортных услуг (transport service provider), а верхние уровни — как потребителя транспортных услуг (transport service user). Разделение на поставщика и пользователя оказывает серьезное влияние на устройство уровней и помещает транспортный уровень на ключевую позицию, поскольку он формирует основную границу между поставщиком и пользователем надежного сервиса передачи данных. Именно этот уровень виден приложениям.
6.1.2. Базовые операции транспортного сервиса
Чтобы пользователи могли получить доступ к транспортному сервису, транспортный уровень должен совершать некоторые действия по отношению к прикладным программам, то есть предоставлять интерфейс транспортного сервиса. У всех транспортных сервисов есть свои интерфейсы. В этом разделе мы вначале рассмотрим простой (но гипотетический) пример транспортного сервиса и его интерфейсов, просто чтобы узнать основные принципы и понятия. Следующий раздел будет посвящен реальному примеру.
Транспортный сервис подобен сетевому, но имеет и некоторые существенные отличия. Главное отличие состоит в том, что сетевой сервис предназначен для моделирования сервисов, предоставляемых реальными сетями со всеми их особенностями. Реальные сети могут терять пакеты, поэтому в общем случае сетевой сервис ненадежен.
Транспортный сервис с установлением соединения, напротив, является надежным. Конечно, реальные сети содержат ошибки, но именно транспортный уровень как раз и должен обеспечивать надежный сервис поверх ненадежной сети.
В качестве примера рассмотрим два процесса, работающих на одной машине, соединенных каналом в системе UNIX (или с помощью любого средства, позволяющего обеспечить взаимодействие процессов). Эти процессы предполагают, что соединение между ними абсолютно идеально. Они не желают знать о подтверждениях, потерянных пакетах, перегрузках и т. п. Им требуется стопроцентно надежное соединение. Процесс A помещает данные в один конец канала, а процесс B извлекает их на другом. Именно для этого и предназначен транспортный сервис с установлением соединения — скрывать несовершенство сетевого сервиса, чтобы пользовательские процессы могли считать, что существует безошибочный поток битов, даже если процессы выполняются на разных машинах.
Кстати, транспортный уровень может также предоставлять ненадежный (дейтаграммный) сервис, но о нем сказать почти нечего (разве что «это дейтаграммы»), поэтому мы в данной главе сконцентрируемся на транспортном сервисе с установлением соединения. Тем не менее существуют приложения, например клиент-серверные вычислительные системы и потоковое мультимедиа, основанные на транспортных сервисах без установления соединения, поэтому ниже мы еще упомянем их.
Второе различие между сетевым и транспортным сервисами состоит в том, для кого они предназначены. Сетевой сервис используется только транспортными подсистемами. Мало кто пишет свои собственные транспортные подсистемы, и поэтому пользователи и программы почти не встречаются с голым сетевым сервисом. Базовые операции транспортного сервиса, напротив, используются многими программами, а следовательно, и программистами. Поэтому транспортный сервис должен быть удобным и простым в употреблении.
Чтобы получить представление о транспортном сервисе, рассмотрим пять базовых операций, перечисленных в табл. 6.1. Этот транспортный интерфейс сильно упрощен, но он дает представление о назначении транспортного интерфейса с установлением соединения. Он позволяет прикладным программам устанавливать, использовать и освобождать соединения, чего вполне достаточно для многих приложений.
Чтобы понять, как могут быть использованы эти операции, рассмотрим приложение, состоящее из сервера и нескольких удаленных клиентов. Вначале сервер выполняет операцию LISTEN — обычно для этого вызывается библиотечная процедура, которая обращается к системе. В результате сервер блокируется, пока клиент не обратится к нему. Когда клиент хочет поговорить с сервером, он выполняет операцию CONNECT. Транспортная подсистема выполняет эту операцию, блокируя обратившегося к ней клиента и посылая пакет серверу. Поле данных пакета содержит сообщение транспортного уровня, адресованное транспортной подсистеме сервера.
Следует сказать пару слов о терминологии. За неимением лучшего термина, для сообщений, посылаемых одной транспортной подсистемой другой транспортной подсистеме, нам придется использовать термин сегмент (segment). Это обозначение используется в TCP, UDP и других интернет-протоколах. В более старых протоколах применяется несколько неуклюжее название TPDU (Transport Protocol Data Unit — модуль данных транспортного протокола). Сейчас оно практически не используется, однако вы можете встретить его в старых статьях и книгах.
Таблица 6.1. Базовые операции простого транспортного сервиса
Базовая операция
Посланный сегмент
Значение
LISTEN (ОЖИДАТЬ)
(нет)
Блокировать сервер, пока какой-либо процесс не попытается соединиться
CONNECT
(СОЕДИНИТЬ)
CONNECTION REQUEST (ЗАПРОС СОЕДИНЕНИЯ)
Активно пытаться установить соединение
SEND (ПОСЛАТЬ)
ДАННЫЕ
Послать информацию
RECEIVE
(ПОЛУЧИТЬ)
(нет)
Блокировать сервер, пока не прибудут данные
DISCONNECT
(РАЗЪЕДИНИТЬ)
DISCONNECTION REQUEST (ЗАПРОС РАЗЪЕДИНЕНИЯ)
Прервать соединение
Сегменты, которыми обменивается транспортный уровень, помещаются в пакеты (которыми обменивается сетевой уровень). Эти пакеты, в свою очередь, содержатся в кадрах, которыми обменивается канальный уровень. Получив кадр, процесс канального уровня обрабатывает заголовок кадра и, если адрес назначения совпадает с местом доставки, передает содержимое поля полезной нагрузки кадра наверх сетевой подсистеме. Точно так же сетевая подсистема обрабатывает заголовок пакета и передает содержимое поля полезной нагрузки пакета наверх транспортной подсистеме. Эта вложенность проиллюстрирована на рис. 6.2.
Рис. 6.2. Вложенность сегментов, пакетов и кадров
Итак, вернемся к нашему примеру общения клиента и сервера. В результате запроса клиента CONNECT серверу посылается сегмент, содержащий CONNECTION REQUEST (запрос соединения). Когда он прибывает, транспортная подсистема проверяет, заблокирован ли сервер операцией LISTEN (то есть заинтересован ли сервер в обработке запросов). Затем она разблокирует сервер и посылает обратно клиенту сегмент CONNECTION ACCEPTED (соединение принято). Получив этот сегмент, клиент разблокируется, после чего соединение считается установленным.