2. Изучение нового учебного материала (способов действий). Цели для преподавателя: - обеспечить понимание планируемого результата деятельности, основных путей его достижения; -способствовать развитию познавательных способностей обучающихся, посредством организации самостоятельной работы. Цели для обучающихся: - рассмотреть детали построения транспортного протокола - рассмотреть надежное установление и разрыв соединения - рассмотреть адресацию - рассмотреть управление протоколов и буферизацию - рассмотреть восстановление после сбоев Цели этапа занятия достигаются посредством: - обеспечения понимания планируемого результата деятельности, основных путей его достижения; - определения критериев, позволяющих обучающимся самостоятельно определять степень достижения запланированного результата; - организации активной самостоятельной деятельности обучающихся по написанию лекции во время занятия.
| 2. Теоретическая часть. Примитивы транспортного уровня. Примитивы транспортного уровня позволяют пользователю получить доступ к транспортному сервису. Транспортный сервис аналогичен сервису сетевого уровня. Однако между ними существует одно различие - сетевой сервис по природе своей ненадежен. Задача транспортного сервиса как раз обеспечить надежную доставку сообщений. Два процесса, соединенные между собой, ничего не должны знать о том, как физически они соединены. Один помещает данные на вход транспортного уровня, другой получает их. Задача транспортного уровня скрыть и от получателя и от отправителя все детали передачи, исправления ошибок и т.п. Теоретически транспортный сервис может быть как ориентированным на соединения, так и нет. Однако дейтаграммный транспортный сервис - это редкость, поэтому мы будем рассматривать транспортный сервис, ориентированный на соединения. Другое важное различие между сетевым и транспортным сервисами состоит в том, кто их использует. Сетевой сервис использует транспортный сервис, а вот транспортный использует пользователь, т.е. прикладные программы. Поэтому транспортный сервис должен быть ориентирован на пользователя, удобным и простым в использовании. Таблица 6-3. Примитивы транспортного сервиса Примитив | Отправляемый пакет TPDU | Значение | LISTEN | (нет) | Блокировка, пока какой-либо процесс не попытается установить соединение | CONNECT | CONNECTION REQ. | Активная попытка установить соединение | SEND | SEND | Информация об отправке | RECEIVE | (нет) | Блокировка до поступления DATA TPDU | DISCONNECT | DISCONNECTION REQ. | Данная сторона собирается прервать соединение | Использование этих примитивов может быть продемонстрировано следующим образом. Сервер приложения выполняет примитив LISTEN, в результате чего он блокируется до поступления запросов от клиентов. Клиент для установления соединения выполняет примитив CONNECT. Транспортный агент на стороне клиента блокирует клиента и посылает серверу пакет с запросом на установление соединения. Напомним, что транспортные агенты обмениваются пакетами, которые имеют специальное название - Transport Protocol Data Unit (TPDU). Рисунок 6-5. Диаграмма состояний при установлении и разрыве соединения В таблице 6-6 показан другой набор примитивов, так называемые сокеты Беркли. В этом наборе два основных отличия от того, что мы только что рассмотрели. Первые четыре примитива выполняются сервером в том порядке, как они указаны в таблице. Примитив SOCKET создает новую точку подключения к серверу, резервирует для нее место в таблице транспортного агента. Параметры обращения определяют формат адреса, тип желаемого сервиса, протокол и т.д. По примитиву BIND сервер выделяет сокету адрес. Причина, по которой адрес выделяется не сразу, в том, что некоторые процессы сами управляют своими адресами, которые жестко закреплены за ними. Второе – LISTEN - не блокирующий примитив. Он выделяет ресурсы и создает очередь, если несколько клиентов будут обращаться за соединением в одно и то же время. Примитив ACCEPT - блокирующий в ожидании запроса на соединение. Таблица 6-6. Сокеты Беркли Примитив | Значение | SOCKET | Создание новой точки подключения | BIND | Прикрепление локального адреса к сокету | LISTEN | Объявление готовности принимать соединения; сообщение о размере очереди | ACCEPT | Блокировка вызывающего в ожидании запроса на соединение | CONNECT | Активная попытка установить соединение | SEND | Отправка данных через данное соединение | RECEIVE | Получение данных через данное соединение | CLOSE | Прерывание соединения | Когда клиент выполняет примитив CONNECT, он блокируется своим транспортным агентом, и запускается процесс установления соединения. Когда он закончится, клиента разблокируют, и начинается обмен данными с помощью примитивов SEND и RECEIVE. Разрыв соединения здесь симметричен, т.е. соединение считается разорванным, если обе стороны выполнили примитив CLOSE. Элементы транспортного протокола. Транспортный сервис реализует транспортный протокол, который используют транспортные агенты. Транспортный протокол в чем-то схож с канальным. Однако между ними несколько различий: Они работают в разных средах (см. рисунок 6-7). Процессы на канальном уровне взаимодействуют непосредственно через физическую среду, поэтому процедура установления соединения много проще. Среда, в которой работает транспортный протокол, использует память, которая может терять свое содержимое. Количество соединений, которое может возникать на транспортном уровне, намного больше, чем количество соединений на канальном уровне, что создает дополнительные проблемы для буферизации и управления потоком. Транспортный протокол должен решать следующие проблемы: Как адресовать прикладной процесс, с которым надо установить соединение? Как корректно установить соединение? Пакеты могут теряться. Как отличить пакеты нового соединения от повторных пакетов, оставшихся от старого? Как корректно разрывать соединение?  Адресация. Проблема адресации состоит в том, как указать, с каким удаленным прикладным процессом надо установить соединение. Обычно для этого используется транспортный адрес, по которому прикладной процесс может слушать запросы на соединение. Вместо него мы будем здесь использовать термин TSAP - Transport Service Access Point. Аналогичное понятие существует и на сетевом уровне - IP-адрес - NSAP для сетевого уровня. На рисунке 6-8 показана взаимосвязь ТSAP и NSAP. Он же иллюстрирует сценарий использования ТSAP для установления соединения между двумя удаленными процессами. Рисунок 6-8. Взаимодействие TSAP и NSAP Из этой иллюстрации не ясно лишь, как прикладной процесс на машине 1 узнает, что интересующий его сервер подключен к ТSAP 122 на машине 2? Одно из возможных решений - если данный сервер всегда подключен к ТSAP 122, и все процессы об этом знают. Такое решение хорошо работает для часто используемого сервиса с длительным периодом активности, но как быть прикладным процессам пользователя, которые активизируются спорадически на короткое время? В операционной системе Unixиспользуется решение, которое называется протоколом установления начального соединения. На каждой машине есть специальный сервер процессов, который представляет все процессы, исполняемые на этой машине. Этот сервер слушает несколько ТSAP, куда могут поступить запросы на ТСР-соединение. Если нет свободного сервера, способного выполнить запрос, то соединение устанавливается с сервером процессов, который переключит соединение на нужный сервер, как только он освободится. Однако есть случаи, когда этот подход с сервером процессов не работает. Не всегда можно запускать сервер сервиса по требованию пользователя. Например, файловый сервер. Он должен существовать всегда. Решение в этом случае - сервер имен. Пользователь устанавливает соединение с сервером имен, для которого ТSAP известен, и передает ему имя сервиса. В ответ сервер имен шлет надлежащий ТSAP. Клиент разрывает соединение с сервером имен и устанавливает его по полученному адресу. Пусть пользователь узнал ТSAP, но как он узнает, на какой машине этот ТSAP расположен, какой сетевой адрес надо использовать? Ответ заключается в структуре ТSAP-адреса, где указана вся необходимая информация. Этот адрес имеет иерархическую структуру. Установление соединения. Проблема установления транспортного соединения сложна потому, что пакеты могут теряться, храниться и дублироваться на сетевом уровне. Типичный пример - установление соединения с банком для перевода денег с одного счета на другой. Из-за перегрузки в сети или по какой-либо другой причине может произойти большая задержка. Тогда по time_out активная сторона вышлет еще один запрос. Пакеты-дубли могут вызвать повторное соединение и вторичный перевод денег. Как быть? Одно из возможных решений - временное ТSAP. После того, как оно использовано, TSAP с таким адресом более не возникает. При этом решении не работает модель с сервером процессов, когда определенные TSAP имеют фиксированные адреса. Другое решение - каждому транспортному соединению сопоставлять уникальный номер. Когда соединение разрывается, этот номер заносится в специальный список. К сожалению, этот список может расти бесконечно. Кроме этого, в случае сбоя машины он может быть потерян, и тогда... Альтернативой может быть ограничение времени жизни пакетов. Достичь этого можно тремя путями: ограничением конструкции подсети установкой счетчиков скачков в каждом пакете установкой временной метки на каждом пакете Заметим, что последний метод требует синхронизации маршрутизаторов в сети. На практике нам надо обеспечить, чтобы стали недействительными не только сами пакеты, но и уведомления о них. Это значит, что надо ввести величину Т – множитель для максимального, реального времени жизни пакета в сети. Его конкретное значение зависит от конкретного протокола и позволяет немного увеличить реальное время жизни так, чтобы по его истечении в сети не осталось ни самого пакета, ни уведомления о нем. При ограничении времени жизни пакета можно построить безопасный способ установления соединения. Этот метод был предложен Томлинсоном (Tomlinson). Его идея состоит в следующем. Все машины в сети оснащены таймерами. Таймер работает даже в случае сбоя машины, т.е. он абсолютно надежен. Каждый таймер - двоичный счетчик достаточно большой разрядности, равной или превосходящей разрядность последовательных чисел, используемых для нумерации пакетов. При установлении соединения значения нескольких младших разрядов этого таймера берутся в качестве начального номера пакета. Главное, чтобы последовательности номеров пакетов одного соединения не приводили к переполнению счетчика и его обнулению. Эти номера можно также использовать для управления потоком в протоколе скользящего окна. Проблема возникает, когда машина восстанавливается после сбоя. Транспортный агент не знает в этот момент, какое число можно использовать для очередного номера. Чтобы избежать повторного использования порядкового номера, который уже был сгенерирован перед сбоем машины, вводится специальная величина по времени, которая образует область запрещенных номеров (см. рисунок 6-10). Рисунок 6-10. (а) TPDU не могут попасть в запрещенную область; (b) Проблема ресинхронизации  Машина, восстановленная после сбоя, не может выбирать номера из этой запретной зоны. Поэтому после восстановления следует подождать Т сек., пока все ранее посланные пакеты не перестанут существовать. На практике поступают иначе, чтобы не тратить впустую эти Т сек. Строят кривую скорости генерации номеров n=at, тогда после сбоя надо выбирать номера по формуле: n=at+T. Проблема номеров может возникать по двум причинам. Либо потому, что машина генерирует слишком быстро пакеты и соединения, либо потому, что делает это слишком медленно. Чем больше разрядность счетчика последовательных номеров, тем дальше отодвигается момент попадания в запретную область. Другая нетривиальная проблема - надежное установление соединения: пакеты ведь могут пропадать. Для ее решения Томлинсон предложил процедуру «троекратного рукопожатия» (three-way handshake). Эта процедура предполагает, что машина 1 шлет запрос на установление соединения под номером x. Машина 2 шлет подтверждение на запрос x, но со своим номером у. Машина 1 подтверждает получение подтверждения с номером у. На рисунке 6-11 (b) и (c) показано, что будет, если поступит запоздавший запрос на соединение и запрос и подтверждение на него. Разрыв соединения. Разрыв соединения, как уже было сказано, может быть асимметричным или симметричным. Асимметричный разрыв может привести к потере данных (см. рисунок 6-12). Рисунок 6-12. Разрыв соединения с потерей данных Симметричный разрыв каждая сторона проводит самостоятельно, когда она передала весь имеющийся объем данных. Однако определить этот факт не всегда просто. Здесь есть одна проблема, которая называется проблемой двух армий. Суть этой проблемы в следующем. Пусть есть две противоборствующие армии, скажем, А и В. Армия А представлена двумя группировками, между которыми расположена армия В. Суммарно ресурсы А превосходят ресурсы В, и, если обе группировки А ударят по В, то А победит. Дело лишь за тем как договорится, чтобы обе группировки ударили одновременно. Имеется сложность – гонец от А должен пройти через территорию, контролируемую В. Пусть группировка №1 шлет гонца с донесением, в котором указано время атаки. Вопрос, выслав гонца, может ли армия №1 выступать? Конечно, нет! Если гонец не доставил донесение, то атака будет отбита, ресурсы потрачены, и В победит. Выход из создавшегося положения – дождаться гонца от армии №2 с подтверждением. Пусть гонец от армии №2 прибыл. Можно ли наступать? Опять нельзя! Не получив подтверждения, что гонец доставил подтверждение, армия №2 не может выступить. Этот процесс ожидания подтверждений можно продолжать сколь угодно долго. Внимательно изучив проблему разрыва соединения, мы придем к выводу, что ни одна армия не начнет атаки до тех пор, пока не получит подтверждения на подтверждение, и так до бесконечности. На самом деле, можно доказать, что нет протокола, который безопасно разрешает эту ситуацию. Обычно эту проблему решают, фиксируя число попыток разрыва. Управление потоком и буферизация. Теперь, рассмотрев, как устанавливают соединение, обратимся к тому, как им управляют. Прежде всего, рассмотрим управление потоком. Проблема управления потоком на транспортном уровне в чем-то аналогична проблеме управления потоком на канальном уровне. Различия в том, что у маршрутизатора число каналов невелико, в то время как на транспортном уровне соединений может быть очень много. Канальный протокол сохранял пакеты как на стороне отправителя, так и на стороне получателя до тех пор, пока они не будут подтверждены. Если у нас есть 64 соединения и поле «время жизни» пакета занимает 4 разряда, то нам потребуется суммарная емкость буферов на 1024 TPDU-пакетов. Число буферов можно сократить, если есть информация о надежности сетевого уровня или о наличии буфера у получателя. На транспортном уровне отправитель сохраняет все пакеты на случай, если какой-то из них придется посылать вторично. Если получатель знает об этом, то он может иметь лишь один пул буферов для всех соединений, и, если пришел пакет и ему нет буфера в пуле, то он сбрасывается, в противном случае сохраняется и подтверждается. Если сетевой уровень не надежный, то на транспортном уровне отправитель вынужден сохранять все отправленные пакеты до тех пор, пока они не будут подтверждены. При надежном сетевом сервисе, наоборот, отправителю нет нужды сохранять отправленные пакеты, если он уверен, что у получателя всегда есть буфер для сохранения полученного TPDU. Если такой уверенности нет, то ему придется сохранять пакеты. Однако и в первом и во втором случае возникает проблема размера буфера. При фиксированной длине буфера естественно организовывать пул буферов одного размера. Однако при переменной длине пакетов проблема становится много сложнее. Если размер буфера устанавливать по максимальной длине пакета, то мы столкнемся с проблемой фрагментации, т.е. неэффективного использования пространства. Если по минимальной длине, то один пакет придется пересылать как несколько, с дополнительными накладными расходами. Можно установить схему динамического согласования размера буфера при установлении соединения. Оптимальное соотношение между буферизацией на стороне отправителя или на стороне получателя зависит от типа трафика. Для низкоскоростного, нерегулярного трафика буферизацию лучше делать на обоих концах. В общем случае вопрос о количестве буферов лучше всего решать динамически. Здесь надо только позаботиться о решении проблемы потери управляющих пакетов. Другую проблему представляет согласование доступного числа буферов и пропускная способность сетевого уровня. Дело в том, что пропускная способность транспортной среды между двумя определенными хостами ограниченна, и если поток между ними превысит пропускную способность транспортной среды, то возникнет перегрузка. Эту проблему лучше всего решать динамически с помощью управляющих сообщений. Механизм управления потоком должен прежде всего учитывать пропускную способность подсети, а уже потом - возможности буферизации. Располагаться этот механизм будет на стороне отправителя, чтобы предотвращать накопление большого числа неподтвержденных сообщений. Мультиплексирование. Потребность в мультиплексировании нескольких потоков одного уровня на одном соединении, виртуальном канале, физической линии на других уровнях возникает постоянно. Эта проблема возникает и на транспортном уровне. Например, если пользователь за терминалом установил транспортное соединение и отошел попить кофе, то транспортное соединение продолжает поддерживаться, под него резервируется буферное пространство, пространство в таблице маршрутизации и т.д. В целях удешевления стоимости транспортных соединений можно отобразить несколько транспортных соединений на одно сетевое. Такое отображение называется нисходящим мультиплексированием. Оно показано схематично на рисунке 6-15 (а). Рисунок 6-15. (а) Восходящее мультиплексирование; (b) Нисходящее мультиплексирование  В некоторых случаях, наоборот, в целях увеличения пропускной способности по отдельным транспортным соединениям можно отобразить транспортное соединение на несколько сетевых и по каждому сетевому иметь свое скользящее окно. Тогда, быстро исчерпав возможности одного оконного буфера, можно переключиться на другое сетевое соединение и продолжить передачу по нему. В этом случае мы получим канал, пропускная способность которого равна сумме пропускных способностей отдельных каналов на сетевом уровне. Такое мультиплексирование называется восходящим (рисунок 6-15 (b)). Восстановление после сбоев. Восстановление после сбоев мы будем рассматривать в предположении, что транспортный агент целиком располагается на абонентской машине. Восстановление сетевого уровня достаточно просто. Если сетевой уровень предоставляет дейтаграммный сервис, то транспортный уровень знает, как исправлять подобные ситуации. При сервисе, ориентированном на соединение, транспортный уровень восстановит потерянное соединение и постарается в диалоге с транспортным агентом на другой стороне выяснить, что успели передать, а что нет. Проблема становится сложнее, когда надо восстанавливать работоспособность машины, включая и транспортный уровень. Рассмотрим случай, когда транспортный сервер взаимодействует с клиентами. Предположим, сервер упал и старается восстановить функционирование. Прежде всего, ему надо узнать у клиента, какое TPDU было последним неподтвержденным, и попросить повторить его. В свою очередь, клиент может находиться в одном из двух состояний: S1 – есть неподтвержденное TPDU, либо S0 – все TPDU подтверждены. Казалось бы, все просто. Однако рассмотрим проблему внимательнее. Сервер, получив TPDU, либо сначала шлет подтверждение, а затем записывает полученное TPDU в буфер приложения, либо сначала записывает, а потом шлет подтверждение. Если сервер упал, послав подтверждение, но до того, как он осуществил запись, то клиент будет находиться после восстановления сервера в состоянии S0, хотя подтвержденное TPDU потеряно. Пусть, наоборот, сервер сначала записал TPDU, а потом упал. Тогда после сбоя сервер найдет клиента в состоянии S1 и решит, что надо повторить неподтвержденное TPDU. В результате получим повторное TPDU. Можно формально показать, что эта проблема только средствами транспортного уровня не решается. Надо, записав TPDU, информировать об этом приложение и только после этого слать подтверждение. При восстановлении надо опрашивать не только клиента на транспортном уровне, но и приложение. |