recv () с нулевой длиной допустим? - PullRequest
10 голосов
/ 13 мая 2011

Используя функцию recv () в C для чтения из сокета 'stream', может ли параметр len быть нулевым?

Функция recv () возвращает ноль для «удаленного соединения закрыто» и количество байтов, фактически прочитанных при нормальной работе, поэтому звучит проблематично, если читать нулевые байты.

приписка
Да, я знаю, чтобы иметь дело с этим отдельно, и не попадаю в эту ситуацию, все же мне интересно, может ли функция справиться с этим, я не могу найти никакой документации об этом.

Ответы [ 5 ]

4 голосов
/ 13 мая 2011

Я верю, что ответ "это зависит". Если это не указано в стандарте (и я действительно верю, что это не так), любая реализация может делать все, что пожелает.

  • Может произойти сбой при EINVAL
  • Он может зависнуть
  • Он может вернуть 0 и продолжить
  • Он может напечатать смешное сообщение и запустить игру мошенника (я понимаю, gcc использовал для этого:)))

На самом деле в моей реализации он возвращает 0 и продолжается.Чтобы проверить, не удалось или просто вернул 0, вы можете проверить errno после вызова, так что это не так проблематично, как вы думаете.

3 голосов
/ 13 мая 2011

Документация для recv в моей системе (Linux) гласит:

Если в сокете нет доступных сообщений, принимающие вызовы ожидают прибытия сообщения

и

Если сообщение слишком длинное, чтобы поместиться в предоставленный буфер, лишние байты могут быть отброшены в зависимости от типа сокета, из которого получено сообщение.

Исходя из документации, я ожидал бы, что мой recv чтобы дождаться сообщения, а затем эффективно отбросить его (UDP) или оставить его в потоке (TCP).

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

Обновление : тестирование показывает, что такое толкование документации является точным.

Сервер:

$ perl -MIO::Socket::INET -E'
   my $s = IO::Socket::INET->new(Listen => 1) or die $!;
   say $s->sockport;

   my $c = $s->accept or die $!;
   say "[".localtime."] connected";

   $c->recv(my $buf, 0) // die $!;
   say "[".localtime."] received";

   say <$c>;
'
39493
[Fri May 13 13:49:53 2011] connected
[Fri May 13 13:49:55 2011] received
foo

Клиент:

$ perl -MIO::Socket::INET -E'
   my $s = IO::Socket::INET->new(
      PeerAddr => "127.0.0.1",
      PeerPort => $ARGV[0],
   ) or die $!;
   sleep 2;
   say $s "foo";
' 39493

(Эти функции Perl - просто тонкие интерфейсы для системных вызовов. Не стесняйтесь переписывать их в C).

1 голос
/ 13 мая 2011

Я почти уверен, что он не определен ... глядя на Linux, он полностью передается "драйверу" (т.е. tcp и т. Д.), Так что это может что-то значить, но опять же я не думаю, что это означает определяется хорошо. Конечно, SuS не говорит об этом ничего явного.

Я думаю, что вам, скорее всего, лучше просто не делать этого и использовать MSG_PEEK с 1 байтом или poll () в зависимости от того, что вы хотите сделать.

0 голосов
/ 14 мая 2011
Страница

POSIX о recv() не совсем понятна. В ненормативной части («Использование приложения») говорится, что recv() в сокете эквивалентно read(), если флаги не заданы. Страница POSIX о read() говорит, что чтение 0 байтов может проверить на ошибки; если ошибки нет или реализация не проверяет, ничего не происходит и возвращается 0.

0 голосов
/ 13 мая 2011

Я не думаю, что параметр длины может быть нулевым, поскольку даже пустая строка (сообщение) должна заканчиваться символом '\ 0'.

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