Транспортный уровень: TCP и UDP
Цели:
- Цельность передаваемых данных и надёжность передачи
- Различение потоков и управление ими
Задачи:
- Передано == принято
Порядок пакетов или один пакет
- Управление процессом передачи
Двустороннее соединение (с проверкой доступности) или один пакет
Подтверждение доставки / ошибки / и т. п. или один пакет
Обмен данными о состоянии канала или один пакет
⇒ Поток или датаграмма
- Идентификация потоков и датаграмм
- Адрес отправителя, адрес получателя
- Порт отправителя, порт получателя
UDP — «один пакет», TCP — поток
Порт + поток ⇒ клиент/сервер. Асимметричная (клиент-серверная) природа транспортных протоколов.
- «Клиент» — инициатор передачи данных, он посылает запрос «серверу»
- «Сервер» — второй участник обмена данными, он «ждёт запроса от клиента»
- ⇒ кто там из них в действительности клиент, а кто сервер, неважно!
TCP |
vs |
UDP |
есть |
подключение |
нет |
есть |
подтверждения |
нет |
есть |
отслеживание цельности потока |
нет |
есть |
отслеживание качества потока |
нет |
несколько |
количество пакетов |
один |
TCP
- Установление (и завершение) соединения
- Подтверждение доставки каждого пакета
- Уведомление об ошибках
- Повторная передача при отсутствии уведомлений
- Окно «одновременно» пересылаемых пакетов
- Поддержка цельности потока / порядка пакетов с помощью Sequential Number
Двунаправленное (т. е. состоит из двух встречных потоков)
Понятие «порт»
- Идентификатор соединения — IP+порт отправителя, IP+порт получателя
Привязка портов: /etc/services и временный порт отправителя.
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) → Кто-то второй
Завершение соединение может инициировать любая сторона.
- У этого алгоритма есть несколько модификаций
(Пример: tcpdump tcp-соединения)
Демо на YouTube
Обработка ошибок и обеспечение надёжности
Получение каждого пакета в каждую сторону нужно подтвердить (ACK)
- Обработка ошибок TCP (если пакет испортился; возможно, если не дошёл)
- Повторная пересылка после тайм-аута (если не пришло подтверждение)
Sliding Window
Средство от всего — Sliding window protocol и «низкий старт».
Статья Лохматого Мамонта на Хабре
На Студопедии (цитата из CCNA)
Больше адаПодробнее на Википедии
Окно — это последовательная группа пакетов из потока, которую можно передавать/получать «одновременно», не дожидаясь подтверждения каждого. При получении очередного пакета окно «сдвигается» на следующий ещё не полученный. Если пакеты идут с разной скоростью или пропадают, в окне получателя образуется «недопринятая» область:
- Непрерывное начало потока уже получено целиком
- Недопринятая область (с неё начинается окно)
- Первый пакет в окне ещё не получен
- Далее — какие-то пакеты в окне получены, какие-то — нет
- Последний из полученных пакетов в окне
- Ещё не полученные пакеты в окне
- Остальные пакеты потока пока только предполагаются ☺
TODO переписать с Flash на
https://github.com/nikhildsahu/Sliding-window-simulator (два алгоритма: Go Back N / Selective Repeat)
https://www2.tkn.tu-berlin.de/teaching/rn/animations/gbn_sr/ (ещё вариант, но там, кажется, что-то не так)
Фиксированное окно
Будем называть «очередными» пакеты, принадлежащие уже полученному потоку, а «внеочередными» — пакеты, принадлежащие недопринятой области окна, т. е. полученные раньше, чем какой-то предыдущий потока.
- Отправитель:
- Передаёт все непереданные пакеты в окне
- Параллельно ждёт получения подтверждения каждому из пакетов
- Подтверждение пакета N означает также подтверждение всех пакетов N-k
- При получении подтверждения пакета N начало окна перемещается на N+1 (появляются ещё непереданные пакеты)
- Для каждого ещё неподтверждённого пакета отслеживается тайм-аут. По истечении тайм-аута пакет посылается повторно.
- При получении диагностики «перешли пакет N» пакет посылается повторно
- Получатель:
- Ждет получения пакетов в окне
- При получении пакета:
Если перед полученным пакетом есть непринятый — получен внеочередной пакет:
Посылается (повторно) подтверждение о получении последнего очередного пакета
Если перед полученным пакетом нет непринятых — получен очередной пакет:
Высчитываются новые границы окна (окно начинается с первого непринятого пакета), в результате изменяется указатель последнего очередного пакета
Посылается подтверждение о получении последнего очередного пакета (это может быть не тот пакет, что был получен только что, потому что в окне могли присутствовать внеочередные пакеты)
- Повторно полученные пакеты игнорируются.
- Если с пакетом что-то не так (не совпадает контрольная сумма и т. п.), отсылается просьба повторной пересылки
Этот алгоритм содержит несколько избыточное количество подтверждений, но:
- Это результат очень простой логики «пакет → подтверждение/ошибка»
- Это позволяет терять (некоторые) подтверждения без влияния на поток
Демо:
В виде .SWF-файла настолько старого, что в современных flash-эмуляторах работает неправильно
Масштабируемое окно
Чем больше окно, тем больше потенциальная пропускная способность:
- Если канал передачи данных готов столько передавать, хорошо!
- Если какое-то устройство на пути передачи данных столько передавать не готово — плохо:
Это устройство будет всегда терять пакеты из большого окна,
…что приведёт в посылке ещё большего количества пакетов (ошибки и повторная передача)
Чем меньше окно, тем меньше пропускная способность (спасибо, Кэп).
Поэтому размер окна может изменяться в зависимости от «качества» канала передачи данных.
На отправителе (т. н. Congestion window)
- Договаривается с получателем о максимальном и минимальном размерах окна
- Начинает с минимального размера
- При каждом сдвиге окна:
Если все пакеты в области сдвига были отосланы с первого раза (без повторов по тайм-ауту или ошибке), окно не только сдвигается, но и увеличивается (например, в два раза, но не больше чем максимальный размер)
- Если со времени последнего сдвига окна были повторные передачи пакетов, или получен анонс уменьшения размера окна, окно уменьшается до минимального
Если получен анонс нулевого размера окна, передача дополнительно приостанавливается на некоторый тайм-аут или до получения другого анонса (что случится раньше)
На получателе (т. н. Receive window)
- Если получатель не справляется с обработкой, он анонсирует меньший максимальный размер окна
Если получатель совсем не справляется с обработкой, он анонсирует нулевой размер окна
Напомним, что TCP — двунаправленное соединение, и во встречном потоке данных действуют те же правила, а абоненты меняются ролями.
Linux: sysctl net.ipv4.tcp_adv_win_scale
кроме того, TCP_window_scale_option
Дурацкое маленькое окошко на медленных / ненадёжных каналах.
Пример масштабирования окна (без обработки ошибок)
В виде .SWF-файла (тоже античного)
У скользящего окна ∃ ещё «быстрый старт» и много-много модификаций…
UDP
- Весь сеанс — одна датаграмма
- Нет шторма подтверждений
- Всё остальное делает прикладной уровень
Применение: DNS, traceroute, DHCP, SNMP, NTP
Использование netcat и socat
TODO поподробнее, м. б. план по ключам и где их использовать?
Netcat — приём-передача данных по сети на стандартный В/В
- Установление TCP-подключения / Однократный приём подключения на TCP-порту
- Установление и приём UDP-«подключения»
- Проблема «окончания сеанса» (нет никакого сеанса, просто поток датаграмм, так что убивать руками)
- немножко умеет в Unix domain сокеты (сокеты в файловой системе)
Socat — приём-передача данных по сети самыми разнообразными способами
руководство, есть статьи попроще ☺
Как используется soсat в наших скриптах: ../01_HardwareAndCommandline/vbconnect
- Главное — не бояться ☺
Другие варианты транспорта?
Идентификатор потока нужен
Порядок пакетов отслеживается, но не гарантируется:
- Цельность желательна, но не полученные вовремя пакеты уже не важны (напр., видео или синхронизация игровых вселенных)
Интеграция с ECN (ACK-и могут быть помечены как предупреждение о забивании канала)
(also, DCCP+UDP для очень старых сетевых устройств и NAT)
SCTP:
Сеанс состоит из «сообщений» произвольного размера (TCP: либо несколько отдельных соединений, непонятно как объединяющихся в один сеанс, либо непрерывный поток, в котором сообщения выделаются уже на прикладном уровне)
Несколько параллельных потоков и multihoming (наконец-то из ID транспортного уровня открутили IP: абоненты рассказывают все свои адреса, а ID служит т. н. «association» и порт)
Двусторонняя готовность к сеансу (4-way handshake вместо 3-way — для отсечения syn flood)
- Порядок сообщений можно отключить
- Дешёвая (не порождающая паразитного трафика) / управляемая / прогнозируемая защита от забивания канала
RSVP (IPv6)
- Резервирование объёмов / пропускной способности / других свойств на всём маршруте
- …
Д/З
Образ не менялся
Задание 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