Функция сокета recv (), возвращающая данные длиной 0 - PullRequest
18 голосов
/ 22 июня 2010

У меня есть приложение, которое установило сокет-соединение на номер порта 5005 с другим устройством (аппаратное устройство с веб-сервером).

Теперь, если мое аппаратное устройство отключается, я теряю связь с устройством.

  1. Означает ли это, что сокет, который я использовал до сих пор, становится недействительным?это разъединение происходит.

  2. Если соединение с сокетом, которое я установил, стало недействительным, тогда почему функция сокета recv () не выдает и SOCKET_ERROR.Вместо этого, почему я получаю данные длиной 0

Ответы [ 6 ]

35 голосов
/ 22 июня 2010

Когда recv возвращает значение 0, что означает, что соединение было закрыто.

См. Справочную страницу recv:

ЭтиCall возвращает количество полученных байтов или -1, если произошла ошибка.Возвращаемое значение будет равно 0, когда одноранговый узел выполнил упорядоченное завершение работы.

В ответе на вопрос № 1 да сокет теперь недействителен.Вы должны создать новый сокет и соединение для дальнейшей связи.

Редактировать

Теперь, как указал Вальдо ниже, существует также возможность иметь полузакрытое TCP-соединение, по которому вы больше не можете получать, кроме вас.можете продолжать запись в сокет, пока вы не закончите отправку своих данных.См. Эту статью для более подробной информации: TCP Half-Close .Это не похоже на то, что у вас такая ситуация.

В ответе на вопрос № 2, в основном, есть два способа обнаружить закрытую розетку.Это предполагает, что сокет прошел упорядоченное завершение работы, то есть одноранговый узел с именем shutdown или close.

Первый метод - чтение из сокета, в этом случае вы получаете возвращаемое значение 0.Другой метод заключается в записи в сокет, что приведет к генерации сигнала SIG_PIPE, указывающего на сломанную трубу.

Чтобы избежать сигнала, вы можете установить опцию MSG_NOSIGNAL socket, в этом случае send вернет -1 и установит errno в EPIPE.

9 голосов
/ 22 июня 2010

Согласен с Робертом С. Барнсом.За исключением утверждения, что сокет теперь «недействителен».

Он все еще действителен.Вы можете использовать это.Вы даже можете отправить данные на одноранговый узел.Единственное, что вы не можете с этим сделать, это позвонить recv.

2 голосов
/ 22 июня 2010

Я полагаю, вы используете TCP для связи с вашим устройством.

  1. Сам сокет все еще "действителен", однако соединение было потеряно.

  2. Вы получаете возвращаемое значение 0 для recv(), когда соединение было закрыто другим хостом (было ли это отключение корректным или нет, не имеет значения)

  3. функции сокетов похожи на C функции: они не генерируют, потому что они могут использоваться в C программах, где существуют исключения , а не .

2 голосов
/ 22 июня 2010

Если recv возвращает 0, это означает, что узел закрыл сокет.

recv не сработает, потому что это функция C.

Если есть ошибка, recv вернет -1. В этом случае ваше приложение должно проверить тип ошибки. Обратите внимание, что возврат -1 не означает, что узел закрыл свой сокет.

1 голос
/ 22 июня 2010

Учитывая, что вы разговариваете с веб-сервером, я предполагаю, что вы используете TCP-сокеты.

Чтобы ответить:

  1. Сокеты нестать недействительным из-за отключения;они просто переходят в отключенное состояние.Все еще безопасно вызывать операции с сокетами на них.

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

  3. На самом деле ответа на этот вопрос нет - это то, как изначально был реализован API сокетов, и мы застряли с этой реализацией, поскольку каждый реализует сокеты Berkley.

0 голосов
/ 26 июня 2018

Чтобы исправить многочисленные искажения в существующих ответах:

  1. Означает ли это, что сокет, который я использовал до сих пор, становится недействительным.

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

Получаю ли я какое-либо специальное сообщение, например, нулевой символ или что-то подобное, когда происходит это отключение.

Нет, вы получаете нулевое возвращаемое значение от recv().Вот для чего это.Он доставляется вне диапазона, а не в буфере данных.

Если соединение с сокетом, которое у меня было, стало недействительным, то почему функция сокета recv() не выдает

Поскольку это C API, а в C нет throws,или в системных вызовах Unix.

и SOCKET_ERROR.

Потому что это не ошибка.

Вместо этого, почему я получаюданные длины 0.

Вы не «получаете данные длины 0».Возвращаемое значение равно нулю вместо данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...