Reputation: 2424
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
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
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
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.
EINVAL
0
and go ongcc
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
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
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