Как проверить, что tcp peer закрыт
У меня есть сетевое соединение TCP с удаленным хостом (windows или linux), если процесс удаленного хоста завершен, recv() завершается неудачно, и я знаю, что соединение закрыто.
но есть ли способ проверить, закрыл ли удаленный хост соединение без фактического получения данных?
Дело в том, что я хочу периодически проверять, жив ли удаленный хост, но я не хочу давать или получать какие-либо данные.
заранее спасибо
2 ответа
Чтобы быть понятным, recv()
не должно произойти сбой, если соединение было закрыто должным образом. Он должен вернуть EOF (0 байт). recv()
потерпит неудачу, если соединение было закрыто ненормально.
Чтобы проверить, было ли соединение закрыто без фактического получения данных, если оно не было, лучшее, что вы можете сделать, это позвонить recvmsg()
с MSG_PEEK
флаг. Просите только один байт. Если соединение было закрыто, вы получите EOF (нормальное закрытие) или ошибку (аварийное закрытие). Если он не был закрыт, вы либо получите EAGAIN
(при условии, что вы переведете сокет в неблокирующий режим) или один байт данных. Итак, да, технически вы получили байт данных, но из-за MSG_PEEK
ядро не записывает тот факт, что вы сделали, так что, как будто вы этого не сделали. Все это предполагает, что вы уже прочитали из буфера ядра все данные из потока, поступившие до того, как могла произойти предполагаемая ошибка.
Конечно, комментарий rakib_ применим: "Нет способа проверить, жив ли удаленный хост, если вы не хотите передавать или получать данные". Это означает, что этот метод не будет обнаруживать сценарии, например, исчезновение удаленного хоста из сети без закрытия соединения и т. Д.
Если вы отслеживаете состояние готовности сокета к чтению с помощью select(), select() вернется и укажет, что сокет имеет данные, готовые для чтения. Затем, когда вы пытаетесь выполнить recv() эти данные, recv() либо потерпит неудачу (если произошла ошибка), либо вернет 0 (чтобы указать EOF, если соединение было чисто закрыто).