Функция сокета recv() возвращает данные длиной 0
У меня есть приложение, которое установило соединение сокета на номере порта 5005 с другим устройством (аппаратное устройство с веб-сервером).
Теперь, если мое аппаратное устройство отключится, я потерял соединение с устройством.
-
Означает ли это, что сокет я был
использование до сих пор становится недействительным.
-
Получаю ли я специальное сообщение, например
нулевой символ или что-то еще
это отключение происходит.
- Если соединение сокета я было
став недействительным, то почему
does not функция recv()
throw и SOCKET_ERROR. Вместо
почему я получаю данные 0
длина.
Спасибо
Ответы
Ответ 1
Когда recv
возвращает значение 0, это означает, что соединение было закрыто.
См. recv
справочная страница:
Эти вызовы возвращают количество полученных байтов или -1, если ошибка произошло. Возвращаемое значение будет равно 0, когда сверстник выполнил упорядоченное завершение работы.
В ответ на вопроС# 1 да, сокет теперь недействителен. Вы должны создать новый сокет и соединение для дальнейших сообщений.
Edit
Теперь, когда valdo указал ниже, есть также возможность иметь полузакрытое TCP-соединение, в котором вы не можете получить больше, но вы можете продолжать писать в сокет, пока не закончите отправлять свои данные. См. Эту статью для получения дополнительной информации: TCP Half-Close. Звучит не так, как будто у вас есть эта ситуация.
В ответе на вопрос № 2 существуют два способа обнаружения закрытого сокета. Это предполагает, что сокет прошел через упорядоченное выключение, что означает, что одноранговый узел называется shutdown
или close
.
Первый способ - прочитать из сокета, в этом случае вы получите возвращаемое значение 0. Другим способом является запись в сокет, что вызовет сигнал SIG_PIPE, указывающий на сломанный канал.
Чтобы избежать сигнала, вы можете установить опцию MSG_NOSIGNAL
socket, и в этом случае send
вернет -1 и установит errno
до EPIPE
.
Ответ 2
Согласитесь с Робертом С. Барнсом. Кроме утверждения, что сокет теперь "недействителен".
Это все еще актуально. Вы можете использовать его. Вы даже можете отправить данные сверстнику. Единственное, с чем вы не можете сделать, это вызов recv
.
Ответ 3
Предположим, вы используете TCP для связи с вашим устройством.
-
Сам сокет по-прежнему "действителен", однако соединение было потеряно.
-
Вы получаете возвращаемое значение 0 для recv()
, когда соединение было закрыто другим хостом (если это отключение было изящным или не имеет значения)
-
Функции сокетов похожи на функции C
: они не выбрасываются, потому что их можно использовать в программах C
, где существуют исключения не.
Ответ 4
Если recv возвращает 0, это означает, что сверстник закрыл сокет.
recv не будет бросать, потому что его функция C.
Если ошибка recv вернет -1. В этом случае ваше приложение должно проверить тип ошибки. Обратите внимание, что возврат -1 не означает, что сверстник закрыл его.
Ответ 5
Учитывая, что вы разговариваете с веб-сервером, я предполагаю, что вы используете сокеты TCP.
Чтобы ответить:
-
Сокеты не становятся недействительными из-за отключения; они просто переходят в отключенное состояние. По-прежнему безопасно вызывать операции сокетов на них.
-
Вы не получите никаких специальных сообщений при отключении. Если вы вызываете recv()
блокирующим образом, он будет возвращаться при отключении, а количество байтов, возвращенных от вызова, не будет соответствовать количеству запрошенных вами байтов.
-
На самом деле нет ответа на этот вопрос: как API-интерфейс сокета был реализован изначально, и мы придерживаемся этой реализации, поскольку все реализуют Berkley Sockets.