Eran
Eran

Reputation: 2424

recv() with length zero is valid?

Using the recv() function in C to read from a 'stream' socket, can the len parameter be zero?

The recv() function returns zero for 'remote connection closed' and the number of bytes actually read on normal operation, so it sounds problematic if it should read zero bytes.

P.S.
Yes I know to deal with it separately, and not get to this situation, still I'm wondering if the function can handle it, I can't find any documentation about it.

Upvotes: 11

Views: 9209

Answers (5)

jilles
jilles

Reputation: 11232

POSIX's page about recv() is not really clear about it. In a non-normative part ("Application Usage"), it says recv() on a socket is equivalent to read() if no flags are given. POSIX's page about read() says a read of 0 bytes may check for errors; if there is no error or the implementation does not check, nothing happens and 0 is returned.

Upvotes: 1

ikegami
ikegami

Reputation: 385917

The documentation for recv on my system (Linux) says

If no messages are available at the socket, the receive calls wait for a message to arrive

and

If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from.

Based on the documentation, I would expect my recv to wait for a message, then effectively discard it (UDP) or leave it in the stream (TCP).

This could be used to test if a non-blocking TCP socket has data waiting.

Update: Testing reveals that this interpretation of the documentation is accurate.

Server:

$ 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

Client:

$ 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

(These Perl functions are just thin interfaces to the system calls. Feel free to rewrite them in C.)

Upvotes: 4

cnicutar
cnicutar

Reputation: 182649

I believe the answer is "it depends". If it is not specified by the standard (and indeed I believe it isn't) any implementation could do as it pleases.

  • It could fail with EINVAL
  • It could hang
  • It could return 0 and go on
  • It could print a funny message and start the game rogue (I understand gcc used to do that :)) )

Actually on my implementation, it returns 0 and goes on. To check if it failed or simply returned 0, you can check errno after the call, so it's not as problematic as you may think.

Upvotes: 3

James Antill
James Antill

Reputation: 2855

I'm pretty sure it's undefined ... looking at Linux it's passed all the way down to the "driver" (ie. tcp, etc.) so it can mean something, but again I don't think that meaning is defined well. Certainly SuS doesn't say anything explicit about it.

I think you are almost certainly better off just not doing it, and using MSG_PEEK with 1 byte or poll() depending on what you want to do.

Upvotes: 1

August Karlstrom
August Karlstrom

Reputation: 11377

I don't think the length parameter can be zero since even an empty string (message) needs to be terminated with '\0'.

Upvotes: -4

Related Questions