NetLab Academy

Сетевые лаборатории в браузере

Войти Начать бесплатно

Теория: TCP и UDP: два способа доставить данные

Порты, рукопожатие и завершение сессии, окно и повторы, и почему голос и видео сознательно выбирают протокол без гарантий. Прочитайте материал, а затем пройдите тест — следующий пункт курса откроется после верных ответов.

Что добавляет транспортный уровень

IP умеет одно: доставить пакет от одного адреса к другому. Он не обещает, что пакет дойдёт, не следит за порядком и не знает, какой программе его отдать. На одном компьютере одновременно работают браузер, мессенджер и почта — и все получают пакеты на один и тот же адрес.

Транспортный уровень закрывает обе дыры. Порт указывает, какому приложению предназначены данные, а выбор между TCP и UDP определяет, будет ли доставка надёжной.

Порты: как пакет находит нужную программу

Порт — число от 0 до 65535. Соединение опознаётся не адресом, а четвёркой: адрес источника, порт источника, адрес назначения, порт назначения. Именно поэтому браузер может открыть десять вкладок одного сайта — адреса и порт назначения совпадают, а порты источника у всех разные.

Порты делятся на диапазоны:
0–1023 — общеизвестные: 22 (SSH), 53 (DNS), 80 (HTTP), 443 (HTTPS), 67/68 (DHCP). В Linux занять такой порт может только привилегированный процесс.
1024–49151 — зарегистрированные за конкретными продуктами.
49152–65535 — временные: их операционная система выдаёт клиенту сама на время соединения.

Отсюда практический вывод: «сервер недоступен» и «порт закрыт» — разные диагнозы. Хост может отвечать на ping и при этом не слушать нужный порт.

TCP: соединение, которое можно потерять и восстановить

TCP даёт то, чего нет у IP: гарантию доставки и порядка. Достигается это не магией, а учётом.

Каждый байт потока пронумерован. Получатель подтверждает, сколько он принял, — это ACK. Не пришло подтверждение вовремя — отправитель шлёт данные заново. Пришли куски не по порядку — получатель сложит их в правильном порядке сам, приложение об этом не узнает.

Плата за надёжность — задержка и накладные расходы. Каждый потерянный кусок приходится ждать и пересылать, а приложение всё это время не получает НИЧЕГО: TCP не отдаёт данные с дырой посередине. Для файла это правильно, для живого разговора — губительно.

Рукопожатие: три пакета до первого байта данных

Прежде чем передать данные, стороны договариваются — это трёхэтапное рукопожатие:

SYN — клиент говорит «хочу соединиться» и сообщает, с какого номера начнёт нумерацию.
SYN-ACK — сервер подтверждает и сообщает свой начальный номер.
ACK — клиент подтверждает ответ сервера.

Только теперь идут данные. Это стоит одного круга задержки — и это видно в дампе: между запросом и первым байтом ответа всегда лежат три служебных пакета.

Диагностически рукопожатие очень удобно. Ушёл SYN, ничего не вернулось — пакет не дошёл или его отбросил межсетевой экран молча. Пришёл RST — хост жив, но порт никто не слушает, и он честно отказал. Это два разных диагноза, и различить их можно одним взглядом в дамп.
Три пакета до первого байта — и что видно в дампе, когда что-то не так
Клиентпорт 51234
Сетьпуть и фильтры
Серверпорт 443
что видно в tcpdump
Диагностический вопрос всегда один: SYN уходит? Не уходит — проблема у нас. Уходит и тишина — фильтруется по дороге. Приходит RST — порт закрыт, и это ответ, а не поломка.

Завершение и состояние TIME_WAIT

Закрывается соединение не в три, а в четыре шага: каждая сторона объявляет, что больше не будет слать данные (FIN), и получает подтверждение. Направления закрываются независимо — одна сторона может закончить передачу и продолжать принимать.

После закрытия инициатор остаётся в состоянии TIME_WAIT примерно на минуту. Это не утечка и не ошибка: так отлавливаются запоздавшие пакеты прежнего соединения, чтобы они не попали в новое с теми же портами.

На нагруженном сервере таких состояний бывают десятки тысяч, и это нормально. Пугаться стоит другого — большого числа SYN_RECV (сервер отвечает, а клиенты не подтверждают) или растущего CLOSE_WAIT (приложение забыло закрыть сокет).

Окно и почему скорость упирается не в канал

Отправитель не ждёт подтверждения на каждый пакет — иначе на длинной линии скорость упала бы до неприличия. Он шлёт столько, сколько разрешает окно, и только потом ждёт.

Отсюда неочевидное следствие: на длинных задержках скорость ограничена окном, а не шириной канала. Канал в гигабит между континентами при маленьком окне даёт скромные мегабиты, потому что отправитель большую часть времени ждёт подтверждений. Именно поэтому «широкий канал, а копируется медленно» — частая и совершенно законная жалоба.

Второй механизм — контроль перегрузки. Потерю пакета TCP считает признаком затора и сам снижает темп. Поэтому одна неисправная линия с потерями роняет скорость сильнее, чем кажется по проценту потерь.

UDP: без гарантий и потому быстрее

UDP не устанавливает соединение, ничего не подтверждает, не восстанавливает порядок и не сбавляет темп. Отправил — и всё.

Звучит как недостаток, но для целого класса задач это единственный разумный выбор. В голосовом звонке пакет, пришедший с опозданием на секунду, не нужен вообще — момент уже прошёл. Лучше пропустить его и продолжить, чем остановить разговор ради пересылки. По той же причине на UDP работают видеосвязь, игры и трансляции.

Есть и второй мотив — цена вопроса. Заголовок UDP — 8 байт против 20 у TCP, и никакого рукопожатия. Для DNS, где запрос и ответ умещаются в один пакет, тратить три пакета на установление соединения было бы расточительством.

Надёжность при этом никуда не девается — её просто переносят в приложение, которое само решает, что переспрашивать, а что пропустить.

Как выбирают между ними

TCP — когда важен каждый байт и порядок: веб, почта, передача файлов, базы данных, SSH.
UDP — когда важнее вовремя, чем полностью: голос, видео, игры, DNS, DHCP, мониторинг.

Выбор делает разработчик приложения, а не администратор сети. Но знать его нужно: диагностика у них разная. У TCP видно рукопожатие, повторы и окно — по дампу понятно, где рвётся. У UDP не видно ничего: пакеты просто перестают доходить, и «работает плохо» приходится ловить по косвенным признакам.

Как проверять

ss -tuln — какие порты слушает хост. t — TCP, u — UDP, l — слушающие, n — без разрешения имён. Первая команда при «сервис не отвечает».

ss -tan state time-wait | wc -l — сколько соединений в TIME_WAIT. Проверять стоит не абсолютное число, а тенденцию.

tcpdump -i eth0 -n 'tcp[tcpflags] & (tcp-syn|tcp-rst) != 0' — только рукопожатия и отказы: сразу видно, доходит ли SYN и чем отвечает та сторона.

tcpdump -i eth0 -n port 53 — UDP-обмен на примере DNS: запрос и ответ, без всякой обвязки.

Главный диагностический вопрос: SYN уходит? Не уходит — проблема у нас. Уходит и тишина — фильтруется по дороге. Приходит RST — порт закрыт, и это ответ, а не поломка.

Команды — шпаргалка

# кто что слушает
ss -tuln                      # -t TCP, -u UDP, -l только слушающие сокеты,
                              #  -n числа вместо имён служб (80, а не http)
ss -tanp                      # -a все сокеты, не только слушающие;
                              #  -p чей это процесс (нужны права root)
ss -tan state time-wait | wc -l
                              # state <имя> — отбор по состоянию сокета;
                              #      wc -l просто считает строки

# поймать рукопожатие и отказы
tcpdump -i eth0 -n 'tcp[tcpflags] & (tcp-syn|tcp-rst) != 0'
                              # в кавычках — фильтр: взять байт флагов в
                              #      заголовке TCP и оставить пакеты, где взведён
                              #      SYN или RST. То есть начала и отказы
tcpdump -i eth0 -n port 80 -c 20
                              # -c 20 — остановиться после 20 пакетов, иначе
                              #      захват идёт до Ctrl-C

# UDP на примере DNS
tcpdump -i eth0 -n port 53    # port 53 ловит и TCP, и UDP: чтобы оставить одно,
                              #      пишут udp port 53

# проверить, открыт ли порт
nc -zv 192.168.1.10 80        # -z проверить и выйти, ничего не передавая;
                              #  -v сказать результат вслух. Дальше адрес и порт
nc -zvu 192.168.1.10 53       # -u — по UDP. Ответа может не быть и при живом
                              #      порте: UDP не обязан подтверждать
Контрольные вопросы

Дальше — лабораторная работа «Разбор TCP-сессии в дампе»

Для неё нужен аккаунт: стенд поднимается персонально под вас — свои роутеры, свои конфиги, никто в них не мешает. Регистрация — почта и пароль.

Теория прочитана. Дальше — руками.

Личный стенд из настоящих роутеров разворачивается за секунды. Платформа проверяет не ответы на тесты, а состояние вашей сети: поднялись ли соседства, сошлись ли маршруты, ходит ли ping. Рядом — AI-наставник, который видит ваши конфиги и ведёт к решению, не выдавая готовое.

Начать бесплатно → бета открыта, доступ бесплатный