Доставка до программы, а не до компьютера
Третий уровень доводит пакет до нужного хоста — и на этом его полномочия заканчиваются. Но на хосте одновременно работают браузер, почтовый клиент, мессенджер, пара фоновых служб. Кому из них отдать пришедшие данные?
Эту задачу решает номер порта. Связка «IP-адрес плюс порт» однозначно указывает на конкретное соединение конкретной программы, и такую связку называют сокетом. Аналогия с адресом дома и номером квартиры затаскана, но точна: улица и дом доведут курьера до подъезда, дальше нужен номер квартиры.
Соединение определяется четырьмя числами
Строго говоря, соединение опознаётся не одним портом, а четвёркой: адрес и порт отправителя плюс адрес и порт получателя. Поэтому сто человек могут одновременно открыть один и тот же сайт на порту 443 — у каждого свой адрес и свой случайный локальный порт, и сервер ничего не путает. По той же причине вы можете держать две вкладки с одним сайтом: соединения различаются локальным портом.
Два протокола на выбор
Транспортных протокола, с которыми вы столкнётесь на практике, ровно два, и различаются они принципиально: TCP гарантирует доставку, UDP — нет. Это не «плохой и хороший», это разные инструменты под разные задачи.
TCP | UDP | |
|---|---|---|
Соединение | Устанавливается заранее | Не устанавливается |
Потери | Переотправит | Потерялось — значит потерялось |
Порядок данных | Гарантирован | Как придёт |
Размер заголовка | 20 байт и больше | 8 байт |
Где используется | Сайты, почта, SSH, передача файлов | DNS, видеозвонки, игры, стриминг |
Логика выбора простая. Если потерянный кусок данных делает результат бессмысленным — половина архива или половина письма никому не нужны, — берут TCP. Если важнее не отстать от реального времени и переспрашивать уже поздно, берут UDP: в разговоре лучше проглотить один слог, чем услышать его через две секунды после ответа собеседника.
Состояния соединений и что они говорят
У TCP-соединения есть состояние, и его видно. Команда ss -tulpn в Linux или netstat -a в Windows показывает список, и по нему легко понять, на каком этапе всё встало.
Состояние | Что означает |
|---|---|
LISTEN | Программа ждёт подключений на этом порту |
SYN_SENT | Запрос ушёл, ответа пока нет |
ESTABLISHED | Соединение установлено и работает |
TIME_WAIT | Соединение закрыто, система придерживает порт на случай опоздавших пакетов |
CLOSE_WAIT | Другая сторона закрыла соединение, а приложение — ещё нет |
Эта картина отвечает сразу на несколько частых вопросов. Занят ли порт вообще. Слушает ли служба на нужном адресе или только на 127.0.0.1 — очень распространённая причина «снаружи не подключается, а локально всё работает». Доходит ли дело до установления соединения: если подключений в ESTABLISHED нет, а в SYN_SENT висит очередь, проблема где-то по дороге — фаервол или маршрут.
Как выглядят обрывы соединений
Соединение может закончиться тремя разными способами, и по тому, каким именно, сразу понятно, где искать причину.
Что видим | Что произошло | Где искать |
|---|---|---|
Connection refused | Пришёл RST — порт активно закрыт | Служба не запущена или слушает другой адрес |
Connection timed out | Ответа нет вовсе | Фаервол молча отбрасывает, либо нет маршрута |
Connection reset by peer | Соединение работало и было оборвано | Упало приложение, сработал таймаут, вмешался посредник |
Третий случай самый интересный. Если соединение обрывается всегда примерно через одно и то же время бездействия, виноват чей-то таймаут: NAT на роутере забыл сессию, балансировщик закрыл простаивающее подключение, прокси решил, что клиент ушёл. Лечится это механизмом keepalive — редкими служебными пакетами, которые напоминают о себе всем по пути. В SSH за это отвечает ServerAliveInterval, в других приложениях — свои настройки, но идея одна.
Что ещё делает транспорт, кроме адресации
TCP занимается не только доставкой по адресу. Он нарезает поток на сегменты подходящего размера, нумерует их, собирает на другом конце в правильном порядке и следит за скоростью.
Окно и управление потоком
Получатель в каждом ответе сообщает размер окна — сколько данных он готов принять прямо сейчас. Если приложение на той стороне не успевает разбирать входящие, окно уменьшается, и отправитель притормаживает. Так медленный получатель не захлёбывается от быстрого отправителя.
Управление перегрузкой
Параллельно TCP следит за самой сетью: заметив потери, резко снижает темп, а потом осторожно разгоняется обратно. Именно поэтому скорость загрузки файла редко бывает идеально ровной, а на первых секундах всегда ниже.
Отсюда неочевидный практический эффект: одна плохая линия на пути (та самая, где растут ошибки CRC на первом уровне) способна обрушить скорость в разы, хотя формально «всё работает», а потери составляют доли процента. TCP честно отрабатывает каждую потерю, но платит за это темпом — и чем длиннее маршрут, тем дороже обходится каждый процент потерь.
Очередь подключений: откуда берутся отказы под нагрузкой
Между «сервер слушает порт» и «приложение обработало запрос» есть промежуточное звено — очередь ожидающих подключений. Ядро принимает входящие соединения и складывает их туда, а приложение забирает по мере готовности. Размер этой очереди называют backlog.
Пока приложение успевает, очередь пустая. Как только оно тормозит — например, полезло в медленную базу, — очередь начинает расти, и при переполнении новые подключения просто отбрасываются. Клиент видит таймаут или отказ, хотя и сеть, и сервер формально живы.
Диагностируется это одной командой: в выводе ss -tulpn есть колонки Recv-Q и Send-Q, и для слушающего сокета первая показывает текущую длину очереди, а вторая — её предел. Ненулевое значение в Recv-Q под нагрузкой означает, что приложение не успевает принимать соединения.
Лечится это не всегда увеличением backlog: больший размер лишь отодвигает момент отказа, а ждать клиент будет дольше. Чаще правильнее разбираться, почему приложение медленно обрабатывает запросы, — очередь здесь симптом, а не болезнь.



