linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Сеть: L4 и выше/tcp-states

kb/network-l4 ── Сеть: L4 и выше ── intermediate

TCP states (LISTEN, ESTABLISHED, TIME_WAIT)

TCP-сессия проходит через 11 состояний от LISTEN до CLOSED. Самые важные на проде: LISTEN, ESTABLISHED, TIME_WAIT, CLOSE_WAIT.

view as markdownaka: tcp-state, time-wait, close-wait

State machine

TCP описывается state machine из 11 состояний (RFC 793). Каждое соединение в каждой стороне находится в одном из них. Переходы происходят при отправке/получении SYN/ACK/FIN/RST или по таймерам.

Стороны клиента и сервера

Server (passive open)         Client (active open)
CLOSED                        CLOSED
  │                             │
  │  listen()                   │  connect()
  ▼                             ▼
LISTEN                        SYN_SENT
  │                             │
  │ rcv SYN, send SYN-ACK       │  rcv SYN-ACK, send ACK
  ▼                             ▼
SYN_RECV                      ESTABLISHED
  │
  │ rcv ACK
  ▼
ESTABLISHED

Главные состояния

  • LISTEN - серверный сокет ждёт SYN. Видно в ss -tln
  • SYN_SENT - клиент отправил SYN, ждёт ответа
  • SYN_RECV - сервер получил SYN, отправил SYN-ACK, ждёт ACK
  • ESTABLISHED - handshake закрыт, можно слать данные
  • FIN_WAIT_1 - мы инициировали закрытие (отправили FIN)
  • FIN_WAIT_2 - peer ACK'нул наш FIN, ждём его FIN
  • CLOSE_WAIT - peer первым отправил FIN, мы ack'нули, наша задача теперь вызвать close(). Если приложение не закрывает - застрянет здесь
  • LAST_ACK - отправили ответный FIN после CLOSE_WAIT, ждём ACK
  • TIME_WAIT - обе стороны послали FIN+ACK; ждём 2*MSL (~60 сек) на случай задержавшихся пакетов
  • CLOSED - нет соединения

TIME_WAIT - почему его так много

После закрытия активная (закрывшая первой) сторона висит в TIME_WAIT ~60 секунд. Это по дизайну - защита от пакетов от старого соединения, попадающих в новое с такой же 4-tuple (src/dst IP+port).

На клиенте, если делает много коротких подключений (HTTP/1.0 без keep-alive, redis-clients без pooling), исходящие порты быстро кончаются:

bash
ss -tn state time-wait | wc -l
# тысячи - потенциальный source-port exhaustion

Решения:

  • HTTP keep-alive / connection pooling в приложении
  • net.ipv4.tcp_tw_reuse=1 - переиспользовать TIME_WAIT-сокеты для исходящих connect (на клиенте)
  • net.ipv4.ip_local_port_range - расширить диапазон ephemeral портов

CLOSE_WAIT - приложение забыло close()

CLOSE_WAIT означает «peer закрыл, ядро ждёт что ты вызовешь close()». Если их растёт со временем - у приложения leak: получает EOF на сокете и не закрывает дескриптор. Классическая ошибка в обработке EOF в node.js / java / питоне.

Видно через ss -tn state close-wait.

§ команды

bash
ss -tn

Все TCP-сессии и их состояния

bash
ss -tnl

Только LISTEN-сокеты (что слушает)

bash
ss -tn state time-wait | wc -l

Сколько TIME_WAIT - сигнал о коротких соединениях

bash
ss -tn state close-wait

Сокеты в CLOSE_WAIT - приложение забывает close() при обнаружении EOF

bash
ss -tnp '( dport = 443 or sport = 443 )'

Что и от кого подключено к 443 (с PID-процессом, нужен sudo)

§ см. также

  • tcp-handshakeTCP three-way handshakeTCP-соединение открывается тремя пакетами: SYN от клиента, SYN-ACK от сервера, ACK от клиента. После - соединение Established, можно слать данные.
  • tcp-keepaliveTCP keepaliveKeepalive шлёт пробы по простаивающему TCP-соединению чтобы поймать мёртвый peer (NAT-таймаут, упавший хост). Дефолт Linux: 7200s простоя, 75s между пробами, 9 проб. Включается через setsockopt(SO_KEEPALIVE).
  • conntrackConntrack - память Linux о всех сетевых соединенияхПодсистема ядра Linux, которая помнит каждое активное соединение. Без неё NAT не развернёт ответ на нужный приватный IP, а фаервол не отличит «новый коннект» от «уже установленного». Видна в `/proc/net/nf_conntrack`.
  • portПорт - как несколько сервисов делят один IP16-битное число (0-65535), идентифицирует **процесс-получатель** на хосте. IP говорит куда (хост), порт - кому (процессу). 80 - HTTP, 443 - HTTPS, 22 - SSH.

§ упоминается в уроках

  • ›advanced-03-tc-netem
  • ›advanced-04-tcp-tuning
  • ›advanced-05-bandwidth-iperf
  • ›intermediate-02-tcp-handshake
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки