2013-05-16 2 views
1

У меня есть TCP-соединение с удаленным хостом. (Windows или linux) если удаленный хост-процесс завершен, recv() не удается a Я знаю, что соединение закрыто.Как проверить tcp peer закрыт

но, есть ли способ проверить, не удался ли удаленный хост без фактического получения данных?

Точка в том, что я хочу периодически проверять, жив ли удаленный хост , но я не хочу давать или получать какие-либо данные.

спасибо заранее

+4

Невозможно проверить, жив ли удаленный хост, если вы не хотите давать или возвращать данные. –

+0

Я думаю, что вы хотите использовать TCP Keep-Alive (используя 'SO_KEEPALIVE') – Hasturkun

+0

@Hasturkun Это все еще требует от вас ввода/вывода, иначе вы никогда не узнаете. – EJP

ответ

4

Чтобы было ясно, recv() не должен потерпеть неудачу, если соединение было правильно закрыто. Он должен возвращать EOF (0 байт). recv() не работает, соединение было закрыто аномально.

Чтобы проверить, было ли соединение закрыто без фактического получения данных, если это не было, лучше всего, возможно, вы можете позвонить по телефону recvmsg() с флагом MSG_PEEK. Попросите только один байт. Если соединение было закрыто, вы получите EOF (нормальное закрытие) или ошибку (аномальное закрытие). Если он не был закрыт, вы получите либо EAGAIN (при условии, что вы вставили сокет в неблокирующий режим), либо один байт данных. Итак, да, технически вы получили байт данных, но из-за MSG_PEEK ядро ​​не фиксирует тот факт, что вы это сделали, так что, как будто вы этого не сделали. Все это предполагает, что вы уже прочитали из буфера ядра все данные из потока, который был до предполагаемой ошибки.

Конечно, комментарий к комментарию rakib применяется: «Невозможно проверить, жив ли удаленный хост, если вы не хотите давать или возвращать данные». Это означает, что этот метод не будет обнаруживать сценарии, такие как удаленный хост, исчезающий из сети, не закрывая соединение, и т. Д.

+0

спасибо! это именно то, что я искал! – daehee

+0

Задавать только один байт, вероятно, недостаточно, так как система может буферизовать до 0,5 МБ, поэтому чтение всего 1 байт будет выглядеть так, что клиент не закрывал соединение. Возможно, подглядывание за 1 МБ обнаружит это. – sheerun

+0

@sheerun хороший пункт. Я должен был сказать, что это позволит вам обнаружить условие, как только вы попали в буфере потока, до такой степени, что предполагаемая ошибка произошла бы. – Celada

1

Если вы контролируете состояние готовности к считыванию сокета через select(), select() будет return и указать, что сокет имеет данные, готовые для чтения. Затем, когда вы пытаетесь recv(), что данные, recv() либо сбой (если была ошибка), либо возврат 0 (чтобы указать EOF, если соединение было закрыто чисто).

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