Транспортный уровень
Содержание
- 1 Транспортный уровень
- 1.1 Функции транспортного уровня
- 1.2 Протоколы транспортного уровня
- 1.3 Мультиплексирование и демультиплексирование
- 1.4 Особенности программирования
- 1.5 Протокол UDP
- 1.6 Принципы надежной передачи данных
- 1.6.1 myTCP2.0 - отправитель
- 1.6.2 myTCP2.0 - получатель
- 1.6.3 myTCP 2.1 - квитанции ведь тоже могут искажаться!?
- 1.6.4 myTCP 3.0 – пакеты могут теряться
- 1.6.5 Недостатки протоколов с ожиданием подтверждений
- 1.6.6 Конвейеризация пакетов. Протоколы скользящего окна
- 1.6.7 Формат TCP-сегмента
- 1.6.8 Порядковые номера и номера подтверждения
- 1.6.9 Протокол TCP. Тройное рукопожатие
- 1.6.10 Борьба с перегрузкой в TCP
- 1.6.11 Механизмы надежной передачи. Обобщение
Транспортный уровень
Функции транспортного уровня
- обеспечивает логическое соединение между приложениями;
- реализует надежную передачу данных;
- обеспечивает контроль скорости передачи данных.
Протоколы транспортного уровня
На транспортном уровне действует два протокола: TCP (надежный) и UDP (ненадежный).
Мультиплексирование и демультиплексирование
Мультиплексирование — сбор сообщений от сокетов всех приложений и добавление заголовков.
Демультиплексирование – распределение приходящих данных по сокетам.
Для UDP нужный сокет определяется номером порта получателя. Для TCP – номером порта получателя, IP-адресом и номером порта отправителя.
Особенности программирования
- Потоковое соединение TCP
- ситуация а) возможна при плохой связи, если промежуток времени между приходами групп дейтаграмм сетевого уровня велик:
- компьютер1 один раз использует функцию send;
- компьютер2 не получает всю информацию за один вызов recv (нужно несколько вызовов).
- ситуация б) возможна, если интервал времени между вызовами функции send мал и размер данных мал:
- компьютер1 использует функцию send несколько раз;
- компьютер2 получает всю информацию за один вызов recv.
- ситуация а) возможна при плохой связи, если промежуток времени между приходами групп дейтаграмм сетевого уровня велик:
- По протоколу UDP
- ситуация а) - невозможна
- компьютер1 один раз использует функцию send, на сетевом уровне UDP-сегмент разбивается на несколько пакетов;
- компьютер2 получает сегмент всегда одним вызовом recv и только, если пришли все IP-дейтаграммы.
- ситуация б) – невозможна
- разные вызовы функции sendto на компьютере1 соответствуют разным UDP-датаграммам и разным вызовам recvfrom на компьютере2.
- ситуация а) - невозможна
- Если буфер в функциях recv и recvfrom меньше, чем размер присланных данных, то в случае UDP часть данных теряется, а в случае TCP – остаток сохраняется для последующего вызова recv.
- У UDP-сервера 1 сокет, а TCP-сервер имеет много разных сокетов (по количеству одновременно подключенных клиентов) и каждому передается своя информация
Протокол UDP
UDP (User Datagram Protocol) выполняет минимум действий, позволяя приложению почти напрямую работать с сетевым уровнем.
Работает гораздо быстрее TCP, потому что не нужно устанавливать соединение и ожидать подтверждения доставки. Возможны потери сегментов. Осуществляет контроль корректности передаваемых данных (контрольная сумма).
Структура UDP-сегмента
Заголовок - всего 8 байт.
Принципы надежной передачи данных
myTCP2.0 - отправитель
myTCP2.0 - получатель
myTCP 2.1 - квитанции ведь тоже могут искажаться!?
Если квитанция искажена – отправитель опять посылает пакет. Получатель должен думать как обрабатывать повторные пакеты (нужно ввести новое состояние – передали прошлый пакет приложению или нет).
Роль идентификаторов «повторный и новый» в TCP/IP играют номера пакетов (т.к. пакеты еще могут теряться).
Главная разница между этими состояниями в том, как обрабатываются повторные пакеты. В состоянии «Прошлый пакет передан приложению» мы выкидываем повторные пакеты, а в состоянии «Прошлый пакет НЕ был передан приложению» мы с радостью их принимаем и передаем приложению.
myTCP 3.0 – пакеты могут теряться
- нужно уметь определять факт потери пакета, например засекать время после того, как отправлен пакет
- нужно нумеровать пакеты
- в квитанциях нужно указывать номер пакета, на который она отправлена
Нужен таймер! В случае, если прошло какое-либо определенное время и подтверждение не пришло, то осуществляется повторная отправка сообщения. Интервал времени – маленький т.к. вероятность потери принимается близкой к 1 – это и вправду так даже для хорошего WiFi-соединения.
Недостатки протоколов с ожиданием подтверждений
Есть 1Гб-канал Ростов - Москва. Время отправки 1000 байт = 8000 бит: 8000 бит / 1 Гб/с = 8 мкс Время распространения сигнала: 1000 км / 300 000 км/с = 3333 мкс Итого: следующие 1000 байт будут отправлены более чем через 6674 мкс Вывод: 99,9% времени канал не используется.
Путь решения – увеличить размер пакета. Но ведь если хотя бы 1 бит исказится, то весь пакет выкинут! Что тогда?
Конвейеризация пакетов. Протоколы скользящего окна
Выход: отправлять пакеты группами без ожидания квитанций – это конвейеризация.
Два подхода: GBN (Go Back N) – возвращение на N пакетов назад SR(Selective Repeat) – выборочное повторение
зеленые – квитанция получены желтые – отправлены, но не получены голубые – подготовлены к отправке белые – нельзя отправлять, пока не получим квитанции на желтые Окно: желтые и голубые – пакеты, которые могут быть переданы без ожидания квитанций Первый белый пакет отправим только после того, как получили подтверждение на первый желтый. Тогда окно подвигается на 1 вправо.
GBN – Получатель отправляет только положительные квитанции и только о получении тех пакетов, для которых выполняется условие: все пакеты с меньшими номерами уже получены. Таким образом, здесь используется групповое квитирование: получение отправителем квитанции с номером i означает, что все пакеты до i доставлены успешно. Если по истечении некоторого времени отправитель не получает квитанции, он повторяет отправление всех N пакетов начиная со следующего за последним квитированным. Метод GBN неэффективен при большом окне и долгом распространении пакетов по сети, в которой случаются потери. Пример: отправили 1000 пакетов, второй не пришел, приходится повторять отправку всех, начиная со второго. Мы «засоряем» сеть бесполезным трафиком. SR – на каждый пакет – своя квитанция.
Вопрос: зачем ограничивать размер окна, давайте все пакеты передадим, а потом будем ожидать подтверждений! Нельзя – так легко получить перегрузку в сети.
Формат TCP-сегмента
TCP-сегмент состоит из поля данных и нескольких полей заголовка. Поле данных содержит фрагмент данных, передаваемых между процессами. Как было показано ранее, размер поля данных ограничивается величиной MSS (максимального размера сегмента). Когда протокол осуществляет передачу большого файла (например, изображения, являющегося частью web-страницы), он, как правило, разбивает данные на фрагменты размером MSS (кроме последнего фрагмента, который обычно имеет меньший размер). Интерактивные приложения, напротив, часто обмениваются данными, объем которых значительно меньше MSS. Например, приложения удаленного доступа к сети, подобные Telnet, могут передать транспортному уровню 1 байт данных. Поскольку обычно длина заголовка ТСР-сегмента составляет 20 байт (на 12 байт больше, чем в UDP), полный размер сегмента в этом случае равен 21 байт. Как и в протоколе UDP, заголовок включает номера портов отправителя и получателя, предназначенные для процедур мультиплексирования и демультиплексирования данных, а также поле контрольной суммы. Кроме того, в состав TCP-сегмента входят еще некоторые поля. □ 32-разрядные поля порядкового номера и номера подтверждения необходимы для надежной передачи данных, о чем будет сказано ниже. □ 4-разрядное поле длины заголовка определяет длину TCP-заголовка в 32-разрядных словах. Минимальный размер составляет 5 слов, а максимальный — 15, что составляет 20 и 60 байт соответственно TCP-заголовок может иметь переменную длину благодаря полю параметров, описанному ниже (как правило, поле параметров является пустым; это означает, что длина заголовка составляет 20 байт). □ Поле флагов состоит из б бит. Бит подтверждения (АСК) указывает на то, что значение, содержащееся в квитанции, является корректным. Биты RST, SYN и FIN используются для установки и завершения соединения. Установленный бит PSH инструктирует получателя протолкнуть данные, накопившиеся в приемном буфере, в приложение пользователя. Наконец, бит URG показывает, что в сегменте находятся данные, помещенные верхним уровнем как «срочные». Расположение последнего байта срочных данных указано в 16-разрядном поле указателя срочных данных. На принимающей стороне протокол TCP должен уведомить верхний уровень о наличии срочных данных в сегменте и передать ему указатель на конец этих данных. (На практике флаги PSH, URG и поле указателя срочных данных не используются. Мы упомянули о них лишь для полноты описания.) □ 16-разрядное окно приема используется для управления потоком данных. Мы увидим, что оно содержит количество байтов, которое способна принять принимающая сторона. □ Указатель важности - 16-битовое значение положительного смещения от порядкового номера в данном сегменте. Это поле указывает порядковый номер октета которым заканчиваются важные (urgent) данные. Поле принимается во внимание только для пакетов с установленным флагом URG. □ Необязательное поле параметров используется в случаях, когда передающая и принимающая стороны «договариваются» о максимальном размере сегмента, либо для масштабирования окна в высокоскоростных сетях. Также в этом поле определяется параметр временных меток. Дополнительную информацию вы можете найти в документах RFC 854 и RFC 1323.
Проблемы с максимальным размером сегмента
TCP требует явного указания максимального размера сегмента (MSS) в случае если виртуальное соединение осуществляется через сегмент сети, где максимальный размер блока (MTU) менее чем стандартный MTU Ethernet (1500 байт). В протоколах туннелирования, таких как GRE, IPIP, а так же PPPoE MTU туннеля меньше чем стандартный, поэтому сегмент TCP максимального размера имеет длину пакета больше, чем MTU. Поскольку фрагментация в подавляющем большинстве случаев запрещена, то такие пакеты отбрасываются.
Проявление этой проблемы выглядит как «зависание» соединений. При этом «зависание» может происходить в произвольные моменты времени, а именно тогда, когда отправитель использовал сегменты длинее допустимого размера. Для решения этой проблемы на маршрутизаторах применяются правила Firewall-а, добавляющие параметр MSS во все пакеты, инициирующие соединения, чтобы отправитель использовал сегменты допустимого размера. MSS может так же управляться параметрами операционной системы.
Порядковые номера и номера подтверждения
Порядковый номер сегмента — это номер первого байта этого сегмента.
Номер подтверждения — это порядковый номер следующего ожидаемого байта.
Порядковые номера и номера подтверждения Поля порядкового номера и номера подтверждения являются наиболее важными в заголовке TCP-сегмента, поскольку играют ключевую роль в функционировании службы надежной передачи данных. Однако перед тем, как рассматривать роль этих полей в механизме надежной передачи, обратимся к величинам, которые протокол TCP помещает в эти поля. Протокол TCP рассматривает данные как неструктурированный упорядоченный поток байтов. Такой подход проявляется в том, что TCP назначает порядковые номера не сегментам, а каждому передаваемому байту. Исходя из этого, порядковый номер сегмента определяется как порядковый номер первого байта этого сегмента. Рассмотрим следующий пример. Пусть хост А желает переслать поток данных хосту В через TCP-соединение. Протокол TCP на передающей стороне неявно нумерует каждый байт потока. Пусть размер передаваемого файла составляет 500 000 байт, величина MSS равна 1000 байт, и первый байт потока имеет порядковый номер 0. TCP разбивает поток данных на 500 сегментов. Первому сегменту присваивается порядковый номер 0, второму сегменту — номер 1000, третьему сегменту— номер 2000, и т. д. Порядковые номера заносятся в поля порядковых номеров каждого ТСР-сегмента.
Теперь рассмотрим номера подтверждения. Вспомним о том, что протокол TCP обеспечивает дуплексную передачу данных, то есть через единственное ТСР-соединение данные между хостами А и В могут передаваться одновременно в обе стороны. Каждый сегмент, исходящий из хоста В, содержит порядковый номер данных, передающихся от хоста В к хосту А. Номер подтверждения, который хост А помещает в свой сегмент, — это порядковый номер следующего байта, ожидаемого хостом А от хоста В. Рассмотрим следующий пример. Предположим, что хост А получил все байты с номерами от 0 до 535, посланные хостом В, и формирует сегмент для передачи хосту В. Хост А ожидает, что следующие байты, посылаемые хостом В, будут иметь номера, начинающиеся с 536, и помещает число 536 в поле номера подтверждения своего сегмента.
Рассмотрим другую ситуацию. Пусть хост А получил от хоста В два сегмента, в первом из которых содержатся байты с номерами от 0 до 535, а во втором — байты с номерами от 900 до 1000. Это означает, что по какой-либо причине байты с номерами от 536 до 899 не были получены хостом А. В этом случае хост А ожидает появления отсутствующих байтов и в поле номера подтверждения своего сегмента помещает число 536. Поскольку TCP квитирует принятые данные до первого отсутствующего байта, говорят, что он поддерживает общее квитирование.
Последний пример демонстрирует очень важный аспект функционирования протокола TCP. Третий сегмент (содержащий байты 900-1000) принят хостом А раньше, чем второй (содержащий байты 536-899), то есть с нарушением порядка следования данных. Возникает вопрос: как протокол TCP реагирует на нарушение порядка? Если полученный сегмент содержит номер последовательности больший, чем ожидаемый, то данные из сегмента буферизируется, но номер подтвержденной последовательности не изменяется. Если в последствии будет принят сегмент, относящийся к ожидаемому номеру последовательности, то порядок данных будет автоматически восстановлен исходя из номеров последовательностей в сегментах. Таким образом TCP относится к протоколам SR, но у него используется общее квитирование как в GBN. Хотя SR – не совсем чистое. Если посылаемая сторона получает несколько (3) отрицательных квитанций на один и тот же сегмент x, то она догадывается, что произошла перегрузка сети и сегменты x+1, x+2, x+3,… тоже не были доставлены. Тогда посылается вся серия начиная с x – как в протоколах GBN.
Протокол TCP. Тройное рукопожатие
Чтобы установить соединение, хост 2 пассивно ожидает входящего соединения, выполняя примитив ACCEPT.
Хост 2 выполняет примитив CONNECT, указывая IP-адрес и порт, с которым он хочет установить соединение, максимальный размер TCP-сегмента и т.п.. Примитив CONNECT посылает TCP-сегмент «Connection request» с установленным битом SYN=1 и сброшенным битом АСК=0 и ждет ответа. Таким образом, хост 1 сообщает порядковый номер x последовательности битов от хоста 1 к 2. Хост 2 отсылает в ответ подтверждение «Connection accepted» (функция accept). Последовательность TCP-сегментов, посылаемых в нормальном случае, показана на рис: SYN=1 ASK=1, хост 2 сообщает порядковый номер x последовательности битов от хоста 2 к 1 и сообщает, что он ожидает продолжения данных начиная с байта № x+1.
Хост 1 (Connect) отправляет подтверждение о получении согласия на установление соединения.
Борьба с перегрузкой в TCP
Когда в какую-либо сеть поступает больше данных, чем она способна обработать, в сети образуются заторы. Интернет в этом смысле не является исключением. Хотя сетевой уровень также пытается бороться с перегрузкой, основной вклад в решение этой проблемы, заключающееся в снижении скорости передачи данных, осуществляется протоколом TCP.
Теоретически, с перегрузкой можно бороться с помощью принципа, заимствованного из физики, — закона сохранения пакетов. Идея состоит в том, чтобы не передавать в сеть новые пакеты, пока ее не покинут (то есть не будут доставлены) старые. Протокол TCP пытается достичь этой цели с помощью динамического управления размером окна.
Первый шаг в борьбе с перегрузкой состоит в том, чтобы обнаружить ее. Пару десятилетий назад обнаружить перегрузку в сети было сложно. Трудно было понять, почему пакет не доставлен вовремя. Помимо возможности перегрузки сети имелась также большая вероятность потерять пакет вследствие высокого уровня помех на линии.
В настоящее время потери пакетов при передаче случаются относительно редко, так как большинство междугородных линий связи являются оптоволоконными (хотя в беспроводных сетях процент пакетов, теряемых из-за помех, довольно высок). Соответственно, большинство потерянных пакетов в Интернете вызвано заторами. Все TCP-алгоритмы Интернета предполагают, что потери пакетов вызываются перегрузкой сети, и следят за тайм-аутами как за предвестниками проблем, подобно шахтерам, наблюдающим за своими канарейками.
Прежде чем перейти к обсуждению того, как TCP реагирует на перегрузку, опишем сначала способы ее предотвращения, применяемые протоколом. При обнаружении перегрузки должен быть выбран подходящий размер окна. Получатель может указать размер окна, исходя из количества свободного места в буфере. Если отправитель будет иметь в виду размер отведенного ему окна, переполнение буфера у получателя не сможет стать причиной проблемы, однако она все равно может возникнуть из-за перегрузки на каком-либо участке сети между отправителем и получателем.
На рис. эта проблема проиллюстрирована на примере водопровода. На рис. а мы видим толстую трубу, ведущую к получателю с небольшой емкостью. До тех пор, пока отправитель не посылает воды больше, чем может поместиться в ведро, вода не будет проливаться, На рис. б ограничительным фактором является не емкость ведра, а пропускная способность сети. Если из крана в воронку вода будет литься слишком быстро, то уровень воды в воронке начнет подниматься и, в конце концов, часть воды может перелиться через край воронки.
Решение, применяемое в Интернете, состоит в признании существования двух потенциальных проблем: низкой пропускной способности сети и низкой емкости получателя — и в раздельном решении обеих проблем. Для этого у каждого отправителя есть два окна: окно, предоставленное получателем, и окно перегрузки. Размер каждого из них соответствует количеству байтов, которое отправитель имеет право передать. Отправитель руководствуется минимальным из этих двух значений. Например, получатель говорит: «Посылайте 8 Кбайт», но отправитель знает, что если он пошлет более 4 Кбайт, то в сети образуется затор, поэтому он посылает все же 4 Кбайт. Если же отправитель знает, что сеть способна пропустить и большее количество данных, например 32 Кбайт, он передаст столько, сколько просит получатель (то есть 8 Кбайт).
При установке соединения отправитель устанавливает размер окна перегрузки равным размеру максимального используемого в данном соединении сегмента. Затем он передает один максимальный сегмент. Если подтверждение получения этого сегмента прибывает прежде, чем истекает период ожидания, к размеру окна добавляется размер сегмента, то есть размер окна перегрузки удваивается, и посылаются уже два сегмента. В ответ на подтверждение получения каждого из сегментов производится расширение окна перегрузки на величину одного максимального сегмента. Допустим, размер окна равен п сегментам. Если подтверждения для всех сегментов приходят вовремя, окно увеличивается на число байтов, соответствующее п сегментам. По сути, подтверждение каждой последовательности сегментов приводит к удвоению окна перегрузки.
Этот процесс экспоненциального роста продолжается до тех пор, пока не будет достигнут размер окна получателя или не будет выработан признак тайм-аута, сигнализирующий о перегрузке в сети. Например, если пакеты размером 1024, 2048 и 4096 байт дошли до получателя успешно, а в ответ на передачу пакета размером 8192 байта подтверждение не пришло в установленный срок, окно перегрузки устанавливается равным 4096 байтам. Пока размер окна перегрузки остается равным 4096 байтам, более длинные пакеты не посылаются, независимо от размера окна, предоставляемого получателем. Этот алгоритм называется затяжным пуском, или медленным пуском. Однако он не такой уж и медленный (Jacobson, 1988). Он экспоненциальный. Все реализации протокола TCP обязаны его поддерживать.
Рассмотрим теперь механизм борьбы с перегрузкой, применяемый в Интернете. Помимо окон получателя и перегрузки, в качестве третьего параметра в нем используется пороговое значение, которое изначально устанавливается равным 64 Кбайт. Когда возникает ситуация тайм-аута (подтверждение не возвращается в срок), новое значение порога устанавливается равным половине текущего размера окна перегрузки, а окно перегрузки уменьшается до размера одного максимального сегмента. Затем, так же как и в предыдущем случае, используется алгоритм затяжного пуска, позволяющий быстро обнаружить предел пропускной способности сети. Однако на этот раз экспоненциальный рост размера окна останавливается по достижении им порогового значения, после чего окно увеличивается линейно, на один сегмент для каждой следующей передачи. В сущности, предполагается, что можно спокойно урезать вдвое размер окна перегрузки, после чего постепенно наращивать его.
Механизмы надежной передачи. Обобщение
- Контрольная сумма;
- Таймер;
- Порядковые номера;
- «+» и «-» квитанции;
- Окно/конвейер.
Контрольная сумма Обнаружение искажений битов в принятом пакете.
Таймер Отсчет интервала ожидания и указание на его истечение. Последнее означает, что с высокой степенью вероятности пакет или его квитанция потеряны при передаче. В случае, если пакет доставляется с задержкой, но не теряется (преждевременное истечение интервала ожидания), либо происходит потеря квитанции, повторная передача приводит кдублированию пакета на принимающей стороне.
Порядковые номера Последовательная нумерация пакетов, посылаемых передающей стороной. «Пробелы» в номерах получаемых пакетов позволяют сделать заключение о потерях данных. Одинаковые порядковые номера пакетов означают, что пакеты дублируют друг друга.
«+» и «-» квитанции Генерируется принимающей стороной и указывает передающей стороне на то, что соответствующий пакет или группа пакетов были или не были приняты. Обычно подтверждение содержит порядковые номера успешно принятых пакетов. В зависимости от протокола различают индивидуальные и групповые подтверждения.
Окно/конвейер Ограничивают диапазон порядковых номеров, которые могут использоваться для передачи пакетов. Групповая передача и квитирование позволяют значительно увеличить пропускную способность протоколов по сравнению с режимом ожидания подтверждений. Размер окна может быть рассчитан на основе возможностей приема и буферизации принимающей стороны, а также уровня загрузки сети.