Э. Таненбаум - Компьютерные сети. (4-е издание) (DJVU) (1130092), страница 157
Текст из файла (страница 157)
Усложнение протокола не помогает. Даже если клиент и сервер обменяются несколькими ТР1)()-модулями, прежде чем сервер попытается записать полу ченный пакет, так что клиент будет точно знать, что происходит на сервере, у него нет возможности определить, когда произошел сбой на сервере: до или после записи. Отсюда следует неизбежный вывод: невозможно сделать отказ и восстановление хоста прозрачными для более высоких уровней. В более общем виде это может быть сформулировано следующим образом; восстановление от сбоя уровня сможет быть осуществлено только уровнем Аг+ 1 и только при условии, что на более высоком уровне сохраняется достаточное количество информации о состоянии процесса.
Как упоминалось ранее, транспортный уровень может обеспечить восстановление от сбоя на сетевом уровне, если каждая сторона соединения отслеживает свое текущее состояние. Эта проблема подводит нас к вопросу о значении так называемого сквозного подтверждения. В принципе, транспортный протокол является сквозным, а не цепным, как более низкие уровни. Теперь рассмотрим случай обращения пользо- Простой транспортный протокол 586 вателя к удаленной базе данных. Предположим, что удаленная транспортная сущность запрограммирована сначала передавать ТР1г()-модуль вышестоящему уровню, а затем отправлять подтверждение.
Даже в этом случае получение подтверждения машиной пользователя не означает, что удаленный хост успел обновить базу данных. Настоящее сквозное подтверждение, получение которого означает, что работа была сделана, и, соответственно, отсутствие которого означает обратное, вероятно, невозможно. Более подробно этот вопрос обсуждается в (Ба)гхег и др., 1984) Стратегия, используемая получающим хостом Сначала запись, потом подтверждение Сначала подтверждение, потом запись Стратегия, используемая передающим хостом ДС(ИГ) ДИГС С(ДИГ) С(УУА) ИГАС Игс(Д) ОК = Протокол работает корректно СОР = Протокол формирует дубликат сообщения ЬОЗТ = Протокол теряет сообщение Рис.
6.15. Различные комбинации стратегий сервера и клиента Простой транспортный протокол Служебные примитивы примера транспортного протокола Первая наша задача будет состоять в том, чтобы как можно более конкретно представить примитивы. С примитивом СОМИГСТ (соединить) все довольно просто: у нас просто будет библиотечная процедура соппесц которую можно вызывать с соответствующими параметрами для установки соединения. Параметрами этой процедуры являются локальный и удаленный ТБАР-адреса. Программа, обра- Чтобы конкретизировать обсуждавшиеся ранее идеи, в данном разделе мы подробно изучим пример реализации транспортного уровня. В качестве абстрактных служебных примитивов будут использоваться ориентированные на соединение примитивы из табл.
6.1. Такие примитивы были выбраны, чтобы сделать пример похожим (с некоторыми упрощениями) на популярный протокол ТСР. 586 Глава б. Транспортный уровень щающаяся к этой процедуре, блокируется (то есть приостанавливается) на время, пока транспортная сущность пытается установить соединение. Если установка соединения проходит успешно, программа разблокируется и может начинать передавать данные.
Когда процесс желает принимать входящие звонки, он обращается к процедуре 11ааеп (ожидать), указывая ТИАР-адрес, соединение с которым ожидается При этом процесс блокируется, пока какой-либо удаленный процесс не попытается установить соединение с его ТИАР-адресом. Обратите внимание: такая модель обладает сильной асимметрией. Пассивная сторона выполняет процедуру 11зТеп и ждет какого-либо события. Активная сторона инициирует соединение.
Возникает интересный вопрос; что делать, если активная сторона начнет первой? Первая стратегия такова: при отсутствии ожидания на пассивной стороне попытка соединения считается неудачной. Другая стратегия заключается в блокировании инициатора (возможно, навсегда), пока на противоположном конце устанавливаемого соединения процесс не перейдет в режим ожидания. Компромиссное решение, используемое в нашем примере, состоит в том, что на установку соединения процедуре соппесг отводится определенный интервал времени. Если процесс хоста, с которым пытаются установить связь, вызовет процедуру 11ааеп прежде, чем истечет интервал ожидания, соединение будет установлено. В противном случае звонящий получает отказ, разблокируется и получает сообщение об ошибке. Для разрыва соединения мы будем применять процедуру 0(зсоппесг. Соединение будет считаться разорванным, когда обе стороны вызовут эту процедуру.
Другими словами, мы используем симметричную модель разъединения. При передаче данных появляется та же проблема, что и при установлении соединения: передатчик активен, а получатель пассивен. Мы будем использовать при передаче данных то же решение, что и при установке соединения: активную процедуру аеп0, передающую данные, и пассивную процедуру гесе1Уе, блокирующую процесс до тех пор, пока не прибудет ТРЕ)Е)-модуль.
Таким образом, наша услуга определяется пятью примитивами: СОИИЕСТ, Е15ТЕИ, 015СОИИЕСТ, 5ЕИО и ИЕСЕ1уЕ. Каждому примитиву соответствует библиотечная служба, выполняющая примитив. Параметры для служебных примитивов и библиотечных процедур следующие: сопппв - Е15ТЕИ (1оса1) соплов СОИИЕСТ (1оса1. гевоге) ааагиа 5ЕИО (соплив. Ьиттег. Ьутеа) атаща - ИЕСЕ1уЕ (соплив, Ьоттег. Ьуаеа) заагпа И5СОИИЕСТ (ссппив) Примитив Е15ТЕИ объявляет о желании обращающейся к нему стороны принимать запросы соединения, обращенные к указанному ТИАР-адресу. Пользователь примитива блокируется до тех пор, пока кто-либо не попытается с ним связаться. Понятия тайм-аута здесь нет.
Примитив СОИИЕСТ имеет на входе два параметра: локальный ТИАР-адрес 1оса1 и удаленный ТИАР-адрес гевоте. Он пытается установить транспортное соедине- Простой транспортный протокол 587 ние между ними. Если это удается, он возвращает в качестве выходного параметра соплов неотрицательное число, используемое для идентификации соединения при следующих вызовах процедур.
Если же установить соединение не удалось, то причина неудачи помещается в соплов в виде отрицательного числа. В нашей простой модели каждый ТИАР-адрес может участвовать только в одном транспортном соединении, поэтому возможной причиной отказа может быть занятость одного из транспортных адресов. Среди других причин могут быть следующие; удаленный хост выключен, неверен локальный адрес или неверен удаленный адрес. Примитив 5Ей0 передает содержимое буфера в виде сообщения по указанному транспортному соединению — может быть, в несколько приемов, если сообщение слишком велико. Возможные ошибки, возвращаемые в виде значения переменной з1згоз, таковы; нет соединения, неверный адрес буфера илн отрицательное число байт.
Примитив йЕСЕ1НЕ означает готовность вызывающего его процесса принимать данные. Размер полученного сообщения помещается в переменную Ьу1ек Если удаленный процесс разорвал соединение или адрес буфера указан неверно (например, за пределами программы пользователя), переменной зГатаз присваивается значение кода ошибки, указывающего на причину возникновения проблемы.
Примитив 015СОллЕСТ разрывает транспортное соединение. Параметр соллоп сообщает номер соединения, которое следует разорвать. Могут возникать, например, такие ошибки: соллоя принадлежит другому процессу пли соплов является неверным идентификатором соединения.
Переменной з1а~цз присваивается О в случае успеха, в противном случае — код ошибки. Транспортная сущность примера транспортного протокола Прежде чем перейти к рассмотрению программы моделирования транспортной сущности, обратите внимание на то, что этот пример аналогичен примерам, приведенным в главе 3: они приводятся скорее в педагогических целях, нежели как серьезное предложение. Многие технические детали (как, например, исчерпывающая обработка ошибок), необходимые для действительно рабочей системы, ради простоты были здесь опущены. Транспортный уровень использует примитивы сетевой службы для отправки и получения ТР1П1-модулей. Нам нужно будет выбрать примитивы сетевой службы, чтобы использовать их в этом примере, Одним из вариантов могла бы быть ненадежная дейтаграммная служба.
Чтобы сохранить простоту примера, мы не стали останавливать свой выбор на этом варианте, так как в этом случае транспортная программа была бы большой и сложной и занималась бы в основном потерянными и опаздывающими пакетами. Кроме того, большая часть этих идей уже достаточно подробно обсуждалась в главе 3. Вместо этого мы решили использовать ориентированную на соединение надежную сетевую службу.