Состояние FIN_WAIT2 когда-либо связано с инициатором тесного соединения? - PullRequest
0 голосов
/ 15 мая 2018

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

Я сбрасываю соединение, выдав POSIX «close ()» для неблокирующейразъем.Затем я запрашиваю новый сокет и восстанавливаю соединение.

Однако я обнаружил одну вещь: все сбросы приводят к "FIN_WAIT2" на старых соединениях.При выполнении команды netstat существует тонна FIN_WAIT2, с которой не связаны никакие идентификаторы PID (я думаю, они считаются осиротевшими и могут пытаться установить тайм-аут соединения с ядром?).

В любом случае, мне любопытно, почему всеиз этих старых соединений складываются в netstat.Я немного прочитал о состояниях TCP, и кажется, что FIN_WAIT2, который я вижу, связан с тем, что сервер (т. Е. Не закрывающий инициатор в моем случае) не отвечает сообщением об успешном закрытии.Почему это так?

Является ли FIN_WAIT2, как правило, связанным с ошибкой на стороне, не закрывающей инициатор?Или это возможно, что я делаю что-то в моем приложении, что препятствует получению сообщения FIN?Имеет ли отношение к тому, что я использую неблокирующие сокеты?

1 Ответ

0 голосов
/ 15 мая 2018

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

Важно понимать, что обе стороны должны прервать соединение с сокетом, чтобы состояние было должным образом очищено. Похоже, ваш сервер не закрывает свой конец сокета. Один из возможных сценариев:

  • Сервер создает сокет прослушивания, связывает его и т. Д.
  • Сервер звонков accept
  • Клиент звонит connect, создавая соединение (состояние TCP с обеих сторон переходит в ESTABLISHED
  • send / recv / send / recv / и т. Д. (Состояние все еще ESTABLISHED)
  • Клиент звонит close; клиентская ОС отправляет FIN пакет на сервер (клиентская ОС перемещает состояние сокета в FIN_WAIT1)
  • Серверная ОС отправляет ACK для подтверждения FIN клиентского компьютера (серверная ОС перемещает состояние сокета в CLOSE_WAIT; клиентская ОС перемещает состояние сокета в FIN_WAIT2)
  • Сервер (программа) никогда не закрывает свой сокет, и, следовательно, серверная ОС никогда не отправляет FIN, поэтому клиентская ОС будет поддерживать сокет в состоянии FIN_WAIT2. (Состояние сокета сервера указано в CLOSE_WAIT)

Состояние сокета на стороне клиента может оставаться в состоянии FIN_WAIT2 в течение длительного времени или даже навсегда, в зависимости от реализации ОС. Например, в Linux есть настраиваемая переменная tcp_fin_timeout, которая указывает, как долго в противном случае будет оставаться неактивное соединение в FIN_WAIT2; но стандарт TCP не определяет время ожидания для FIN_WAIT2. (Обратите внимание, что клиентская программа ничего об этом не знает. Она закрыла сокет, дескриптор файла сокета был уничтожен и сокет больше не доступен для него; все это обрабатывается операционной система.)

Если это именно то, что произошло, вы можете попробовать перезапустить серверную программу (потому что, когда вы завершаете процесс сервера, операционная система сервера автоматически закрывает все свои открытые файлы, и это приведет к отправке FIN s на любой еще открытые розетки). Я думаю, вы увидите, что перезапуск сервера приводит к тому, что все эти сокеты на стороне клиента переходят в состояние TIME_WAIT, где они останутся на короткое время, прежде чем исчезнут сами по себе. (Там - это механизм тайм-аута, указанный для TIME_WAIT.)

См. Также диаграмму состояния TCP:

TCP State Diagram

...