Recv() с нулевой длиной?
Используя функцию recv() в C для чтения из сокета 'stream', может ли параметр len быть нулевым?
Функция recv() возвращает ноль для "удаленного подключения закрыта" и количество фактически прочитанных байтов при нормальной работе, поэтому звучит проблематично, если он должен читать нулевые байты.
P.S.
Да, я знаю, чтобы иметь дело с этим отдельно, и не добираться до этой ситуации, все же мне интересно, может ли функция справиться с этим, я не могу найти документацию об этом.
Ответы
Ответ 1
Я считаю, что ответ "это зависит". Если он не указан стандартным (и, действительно, я считаю, что это не так), любая реализация может делать, как это угодно.
- Это может привести к ошибке с
EINVAL
- Он может висеть
- Он может вернуться
0
и продолжить
- Он может печатать забавное сообщение и запускать игру изгоев (я понимаю, что
gcc
использовал это:)))
Фактически на моей реализации он возвращает 0 и продолжает. Чтобы проверить, не сработал или просто вернулся 0, вы можете проверить errno
после вызова, поэтому он не так проблематичен, как вы думаете.
Ответ 2
Документация для 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.)
Ответ 3
Я почти уверен, что это undefined... глядя на Linux, он прошел весь путь до "драйвера" (т.е. tcp и т.д.), поэтому это может означать что-то, но опять же я не думаю этот смысл определен хорошо. Конечно, SuS ничего не говорит об этом.
Я думаю, что вам почти наверняка лучше не делать этого и использовать MSG_PEEK с 1 байтом или опросом() в зависимости от того, что вы хотите сделать.
Ответ 4
Страница POSIX о recv()
на самом деле не совсем понятна. В ненормативной части ( "Применение приложения" ) говорится, что recv()
в сокете эквивалентно read()
, если флаги не указаны. На странице POSIX около read()
говорится, что чтение из 0 байтов может проверять наличие ошибок; если нет ошибки или реализация не проверяет, ничего не происходит и возвращается 0.
Ответ 5
Я не думаю, что параметр длины может быть нулевым, так как даже пустую строку (сообщение) нужно завершить с помощью "\ 0".