Linux - тайм-аут при отключенной отправке
Я занимаюсь разработкой серверного приложения, и у меня возникла следующая проблема с отправкой данных клиенту, которая внезапно разрывает соединение.
Когда я звоню send
на сокете блокировки с тайм-аутом записи, установленным через setsockopt(SO_SNDTIMEO)
и клиент отключается во время отправки (т. е. отправляется несколько байтов, затем клиент правильно завершает TCP - как видно из wireshark), send
все еще блокирует, пока не истечет время ожидания отправки. Следующий звонок send
возвращает ошибку, как и ожидалось.
Я ожидаю, что завершение TCP (FIN/ACK) приведет к блокировке send
чтобы вернуться немедленно, а не после истечения времени ожидания.
Кто-нибудь когда-нибудь видел такое поведение? Это нормально?
1 ответ
Нет, FIN, отправленный с клиента, не разблокирует send()
на сервере. Когда клиент звонит close()
FIN отправляется на сервер, и соединение закрывается для направления от клиента к серверу. Направление от сервера к клиенту все еще открыто до вызова сервера close()
и FIN отправляется клиенту.
Когда клиент отправляет FIN, а сервер отправляет ACK обратно, соединение на сервере находится в состоянии CLOSE_WAIT, а соединение на клиенте - в состоянии FIN_WAIT_2. Сервер по-прежнему может отправлять данные, а клиент по-прежнему может получать данные, пока сервер не закроет соединение.
Закрытое соединение не может быть обнаружено через send()
, Только recv()
обнаруживает соединение, закрытое узлом
Если ваш код должен выполнить немедленное действие, когда клиент закрывает соединение, он должен вызвать poll()
или же select()
и использовать неблокирующие send()
а также recv()
звонки.