2010-08-30 1 views
2

Когда мой код находится в блокирующем recv-вызове, если другая сторона перезагружается, этот вызов стороны recv не узнает об этом и просто переходит в завитое состояние.В случае блокировки вызова recv, если перезагрузка системы с одноранговой системой, вызов не выходит извне. Зачем?

Как этого избежать?

ответ

8

По умолчанию, если другая сторона соединения исчезает, не прерывая соединение должным образом, ОС на вашей стороне не знает, что дальнейшие данные не появятся. Вот почему recv() будет блокироваться навсегда в этой ситуации.

Если вы хотите получить тайм-аут, установите для него неблокирующий и используйте select(), чтобы дождаться, когда он станет читаемым. select() позволяет указать время ожидания.

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

+0

Спасибо за ответ. Как насчет отправки? Будет ли она также сталкиваться с аналогичной проблемой? – Jay

+0

@Jay: 'send()' будет разблокировать после (в худшем случае) 4,5 минуты с ошибкой, так как другая сторона не будет отправлять ACK, а ACK имеют таймаут. TCP - это протокол, ориентированный на данные: до тех пор, пока вы не видите ошибки, данные не были потеряны. Но он ничего не может сказать о состоянии другой стороны. В вашем случае это ничем не отличается от простоя TCP-соединения. Вот почему ваш 'recv()' блокирует по существу навсегда. – Dummy00001

+0

Хорошо. Еще раз спасибо. Если я использую Non-Blocking Sockets, то он всегда будет давать мне EWOULDBLOCK для отправки и возврата в этом сценарии правильно? – Jay

Смежные вопросы