Транспортный уровень: TCP и UDP
(здесь планировался ещё разговор про NAT, но он не получился)
Цели:- Цельность передаваемых данных и надёжность передачи
- Различение потоков и управление ими
Задачи:
- Передано == принято
Порядок пакетов или один пакет
- Управление процессом передачи
Двустороннее соединение (с проверкой доступности) или один пакет
Подтверждение доставки / ошибки / и т. п. или один пакет
Обмен данными о состоянии канала или один пакет
⇒ Поток или датаграмма
- Идентификация потоков и датаграмм
- Адрес отправителя, адрес получателя
- Порт отправителя, порт получателя
UDP — «один пакет», TCP — поток
Порт + поток ⇒ клиент/сервер. Асимметричная (клиент-серверная) природа транспортных протоколов.
- «Клиент» — инициатор передачи данных, он посылает запрос «серверу»
- «Сервер» — второй участник обмена данными, он «ждёт запроса от клиента»
- ⇒ кто там из них в действительности клиент, а кто сервер, неважно!
Привязка портов: /etc/services и временный порт отправителя.
TCP
- Установление (и завершение) соединения
- Подтверждение доставки каждого пакета
- Уведомление об ошибках
- Повторная передача при отсутствии уведомлений
- Окно «одновременно» пересылаемых пакетов
- Поддержка цельности потока / порядка пакетов с помощью Sequential Number
Двунаправленное (т. е. состоит из двух встречных потоков)
Sequential Number
Задачи:
- Порядковая нумерация пакетов в потоке (на случай переупорядочивания)
- Контроль целостности потока пакетов (на случай удвоения / потери)
Решение:
- SEQN (Sequential Number) — объём переданных байтов в потоке:
- передаётся в каждом пакете,
- изначально выбирается случайным,
- прирастает на объём переданных байтов.
- ⇒ это и нумерация (последовательность), и проверка потерь (несовпадение SEQN и действительного объёма)
Подключение
Пакеты могут носить с собой т. н. флаги — это способ управления соединением
3-way handshake — установление двунаправленного соединения (флаг SYN — запрос на подключение, флаг FIN — запрос на отключение, флаг ACK — подтверждение получения пакета):
Client → (SYN1) → Server
Client ← (ACK1+SYN2) ← Server
Client → (ACK2+PAYLOAD) → Server
- …
Кто-то первый → (FIN1) → Кто-то второй
Кто-то первый ← (ACK1+FIN2) ← Кто-то второй
Кто-то первый → (ACK2) → Кто-то второй
Завершение соединение может инициировать любая сторона.
- У этого алгоритма есть несколько модификаций
Обработка ошибок и обеспечение надёжности
Получение каждого пакета в каждую сторону нужно подтвердить (ACK)
- Обработка ошибок TCP (если пакет испортился; возможно, если не дошёл)
- Повторная пересылка после тайм-аута (если не пришло подтверждение)
Sliding Window
Средство от всего — Sliding window protocol и «низкий старт».
Статья Лохматого Мамонта на Хабре
На Студопедии (цитата из CCNA)
Больше адаПодробнее на Википедии
Окно — это последовательная группа пакетов из потока, которую можно передавать/получать «одновременно», не дожидаясь подтверждения каждого. При получении очередного пакета окно «сдвигается» на следующий ещё не полученный. Если пакеты идут с разной скоростью или пропадают, в окне получателя образуется «недопринятая» область:
- Непрерывное начало потока уже получено целиком
- Недопринятая область (с неё начинается окно)
- Первый пакет в окне ещё не получен
- Далее — какие-то пакеты в окне получены, какие-то — нет
- Последний из полученных пакетов в окне
- Ещё не полученные пакеты в окне
- Остальные пакеты потока пока только предполагаются ☺
Фиксированное окно
Будем называть «очередными» пакеты, принадлежащие уже полученному потоку, а «внеочередными» — пакеты, принадлежащие недопринятой области окна, т. е. полученные раньше, чем какой-то предыдущий потока.
- Отправитель:
- Передаёт все непереданные пакеты в окне
- Параллельно ждёт получения подтверждения каждому из пакетов
- Подтверждение пакета N означает также подтверждение всех пакетов N-k
- При получении подтверждения пакета N начало окна перемещается на N+1 (появляются ещё непереданные пакеты)
- Для каждого ещё неподтверждённого пакета отслеживается тайм-аут. По истечении тайм-аута пакет посылается повторно.
- При получении диагностики «перешли пакет N» пакет посылается повторно
- Получатель:
- Ждет получения пакетов в окне
- При получении пакета:
Если перед полученным пакетом есть непринятый — получен внеочередной пакет:
Посылается (повторно) подтверждение о получении последнего очередного пакета
Если перед полученным пакетом нет непринятых — получен очередной пакет:
Высчитываются новые границы окна (окно начинается с первого непринятого пакета), в результате изменяется указатель последнего очередного пакета
Посылается подтверждение о получении последнего очередного пакета (это может быть не тот пакет, что был получен только что, потому что в окне могли присутствовать внеочередные пакеты)
- Повторно полученные пакеты игнорируются.
- Если с пакетом что-то не так (не совпадает контрольная сумма и т. п.), отсылается просьба повторной пересылки
Этот алгоритм содержит несколько избыточное количество подтверждений, но:
- Это результат очень простой логики «пакет → подтверждение/ошибка»
- Это позволяет терять (некоторые) подтверждения без влияния на поток
Демо:
В виде .SWF-файла настолько старого, что в современных flash-эмуляторах работает неправильно
Масштабируемое окно
Чем больше окно, тем больше потенциальная пропускная способность:
- Если канал передачи данных готов столько передавать, хорошо!
- Если какое-то устройство на пути передачи данных столько передавать не готово — плохо:
Это устройство будет всегда терять пакеты из большого окна,
…что приведёт в посылке ещё большего количества пакетов (ошибки и повторная передача)
Чем меньше окно, тем меньше пропускная способность (спасибо, Кэп).
Поэтому размер окна может изменяться в зависимости от «качества» канала передачи данных.
На отправителе (т. н. Congestion window)
- Договаривается с получателем о максимальном и минимальном размерах окна
- Начинает с минимального размера
- При каждом сдвиге окна:
Если все пакеты в области сдвига были отосланы с первого раза (без повторов по тайм-ауту или ошибке), окно не только сдвигается, но и увеличивается (например, в два раза, но не больше чем максимальный размер)
- Если со времени последнего сдвига окна были повторные передачи пакетов, или получен анонс уменьшения размера окна, окно уменьшается до минимального
Если получен анонс нулевого размера окна, передача дополнительно приостанавливается на некоторый тайм-аут или до получения другого анонса (что случится раньше)
На получателе (т. н. Receive window)
- Если получатель не справляется с обработкой, он анонсирует меньший максимальный размер окна
Если получатель совсем не справляется с обработкой, он анонсирует нулевой размер окна
Напомним, что TCP — двунаправленное соединение, и во встречном потоке данных действуют те же правила, а абоненты меняются ролями.
Дурацкое маленькое окошко на медленных / ненадёжных каналах.
Пример масштабирования окна (без обработки ошибок)
В виде .SWF-файла (тоже античного)
У скользящего окна ∃ ещё «быстрый старт» и много-много модификаций…
UDP
- Весь сеанс — одна датаграмма
- Нет шторма подтверждений
- Всё остальное делает прикладной уровень
Применение: DNS, traceroute, DHCP, SNMP, NTP
Использование netcat и socat
TODO
Socat (введение!)
руководство, есть статьи попроще ☺
Другие варианты транспорта?
Поток нужен, порядок уже неважен (напр., видео): DCCP (или DCCP+UDP)
Несколько потоков в одном сеансе, двусторонняя готовность к сеансу (4-way handshake вместо 3-way): SCTP
Дешёвая / управляемая / прогнозируемая защита от забивания канала: ECN
Резервирование объёмов / пропускной способности / других свойств: RSVP (IPv6)
Д/З
Новое в образе: conntrack, ssh для root и приколы для лекций ☺
Задание 6
Суть: Почитать документацию по socat (руководство, есть статьи попроще ☺) и организовать проброс TCP-соединения и UDP-датаграммы без использования маршрутизации.
- Площадка: Клиент-1 ←сеть1→ Клиент-2 ←Сеть-2→ Клиент-3
- Настроить сеть на всех хостах заранее, в отчёт не входит
- Отчёт:
(на Клиенте-1) report 6 client1
Запустить socat в режиме listen на каком-нибудь TCP-порту с перенаправлением вывода на стандартный вывод
(на Клиенте-2) report 6 client2
Запустить socat в режиме listen на каком-нибудь TCP-порту и выводом на TCP-порт Клиента-1
(на Клиенте-3) report 6 client3
Запустить cal и перенаправить с помощью socat вывод на TCP-порт Клиента-2
В результате этой команды на Клиенте-1 появится вывод cal и все socat-ы остановятся
- (снова на Клиенте-1, report не останавливаем)
Запустить socat в режиме UDP-RECVFROM: (см. документацию) на каком-нибудь UDP-порту с перенаправлением вывода на стандартный вывод
- (снова на Клиенте-2, report не останавливаем)
Запустить socat в режиме UDP-RECVFROM: на каком-нибудь UDP-порту с выводом на UDP-порт Клиента-1 (режим UDP-SENDTO:)
- (снова на Клиенте-3)
Запустить cal и перенаправить с помощью socat (режим UDP-SENDTO:) вывод на UDP-порт Клиента-2
В результате этой команды на Клиенте-1 появится вывод cal и все socat-ы остановятся
- Остановить все report-ы
Три отчёта (названия сохранить, должно быть: report.06.client1, report.06.client2 и report.06.client3) переслать одним письмом в качестве приложений на uneexlectures@cs.msu.ru