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), исходящие порты быстро кончаются:
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.