Typing man recv()
on my system, I get:
ssize_t
recv(int socket, void *buffer, size_t length, int flags);
…
RETURN VALUES
These calls return the number of bytes received, or -1 if an error occurred.
Note that length
is of unsigned type size_t
and the function's result is a signed ssize_t
.
If passed a value larger than SSIZE_MAX
for length
, how theoretical is the situation where recv()
would fill the memory pointed by buffer
and return a negative value other than -1
? Are there types of sockets that allow very long messages (Unix domain?)? What about MSG_WAITALL
?
Here's what the Posix 2008 rationale has to say about ssize_t (extracted from B.2.12 Data Types):
ssize_t
This is intended to be a signed analog of size_t. The wording is such that an implementation may either choose to use a longer type or simply to use the signed version of the type that underlies size_t. All functions that return ssize_t (read() and write()) describe as "implementation-defined" the result of an input exceeding {SSIZE_MAX}.
Actually, that's not quite true, since the socket functions which return ssize_t
, including recv
, don't mention anything about input exceeding SSIZE_MAX
. So I'm taking that as a statement of intention, implying that the missing wording in recv
is an error which might be corrected some day.
In short, if you want to write portable code, you need to ensure that your I/O segments do not exceed SSIZE_MAX
. Furthermore, SSIZE_MAX
may be as small as 32767. So portable code shouldn't assume that it might be greater.
However, not everyone cares that much about portability. You might know something about the implementations your code runs on. Posix continues:
It is recognized that some implementations might have ints that are smaller than size_t. A conforming application would be constrained not to perform I/O in pieces larger than {SSIZE_MAX}, but a conforming application using extensions would be able to use the full range if the implementation provided an extended range, while still having a single type-compatible interface.
Posix does guarantee that the only values returned by recv
are -1, 0 or the number of bytes received. A conforming implementation, according to the above wording, could map values greater than SSIZE_MAX
but less than or equal to 2*SSIZE_MAX
onto the negative integers other than -1
. (How this might be accomplished is left as an exercise for the interested reader :) ). Linux does not, as far as I know, document any such extension, though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With