Is it ever possible for the C send
function to return zero when using TCP sockets? The man page just says that it will return the number of bytes sent, but I am not sure if it will just return -1 when it can't send any data.
6 Answers
I'm pretty certain, though the memory is deep in the mists of time, that I've seen it return zero before, in the situation of massive data transfers where the other end was not keeping up.
From memory, in that case, the remote TCP stack buffers had filled up, the stack had notified the local end that it was to delay until some space was cleared out and the local buffers had filled up as well.
At that point, it's not technically an error (hence no -1 returned) but no data could be accepted by the local stack.
I'm not entirely certain that's the case now since the current Posix standard seems to indicate it will simply block in that case (or fail if it's set up for non-blocking).
However, I suspect it's a moot point. You do have the possibility that it will return less than the bytes you requested to send and you therefore should have code in place to handle that.
And, since it will be pretty much the same logic handling 'one less than what you requested' as handling 'zero bytes', you may as well assume it can return zero.

- 854,327
- 234
- 1,573
- 1,953
-
2How should I handle it? Should my program keep trying to send, or should it fail? – Adrian Jun 21 '10 at 04:25
-
3You should keep trying to send since it's not an error condition. If it doesn't recover, then you'll eventually get back an error. That's the point where you should indicate failure. One thing you _may_ want to consider is to introduce a delay following a zero return code before retrying. That would give more time for a temporary problem to right itself. There are a number of strategies you could follow for that. – paxdiablo Jun 21 '10 at 04:31
-
wouldn't this only be in a non-blocking scenario? – jdizzle Jun 21 '10 at 04:40
-
_That_, I think, is implementation-dependent. I'm pretty certain Linux doesn't return until it's all sent (or an error is returned) but I know of at least one BSD where it may send less than what was requested. It's then up to the client code to resend the bit that didn't go out on the previous attempt. – paxdiablo Jun 21 '10 at 05:42
-
@paxdiablo: it is normal behavior when send() sends less than request. e.g. when portion was already sent and syscall got interrupted by signal. It can't return -1/EINTR since some of the input was already consumed. I guess return of 0 is of similar nature. – Dummy00001 Jun 21 '10 at 15:52
-
9@paxdiablo: I do not think your explanation is right. If the socket is in blocking mode, and the receiver reports its receive buffer is full, then send() simply blocks until it can send data again (or a fatal error/timeout occurs). If the socket is in non-blocking mode instead, then it returns immediately with -1 and an error code of EWOULDBLOCK. In my experience, a return value of 0 always means that either 0 bytes were passed to send(), or the other party has gracefully closed the socket (or at least called shutdown(0)). – Remy Lebeau Jun 23 '10 at 22:36
-
@Remy, as I said, it depends on the implementattion. AIX4, where I saw the behaviour, is one example. Online docs seem to indicate FreeBSD is the same although the Linux docs state otherwise. Try it under FreeBSD with the receiving side not recv'ing the data and I suspect you'll eventually see a 0 return from a non-zero send. But regardless of that, since the docs state that it _can_ return zero, you should code for it, no matter what happens in reality. Behaviour may change in a future release or your code may be ported. – paxdiablo Jun 23 '10 at 23:16
-
8@RemyLebeau I agree. The behaviour of send() is not implementation-dependent, contrary to what is asserted in this answer. It was defined by BSD and then Posix, decades ago. However your comment about 'the other party has gracefully closed' isn't correct. That will cause ECONNRESET if you keep sending, not a return code of zero. – user207421 Feb 24 '14 at 07:39
-
@EJP, I didn't state in the answer that it was implementation dependent, just in a comment answering jdizzle's query on whether it only applied to non-blocking sockets (and then it was only a comment that I _thought_ that's how an early AIX behaved). So the _answer_ (IMO) is still correct, POSIX states that it _can_ return zero under certain circumstances, so you may be better off coding for that, regardless of the actual reason. – paxdiablo Feb 24 '14 at 09:59
-
Of course, if you can actually identify part of the answer that you think is wrong, and cite a source, I'd be happy to admit I'm wrong and change it. – paxdiablo Feb 24 '14 at 10:01
-
My sources are the BSD *man* pages and the Posix specification. The former states 'If no messages space is available at the socket to hold the message to be transmitted, then `send()` normally blocks, unless the socket has been placed in non-blocking I/O mode.' The latter specifically states that in blocking mode *all* data is transferred. In both cases the possibility of returning zero is, err, zero. – user207421 Feb 28 '16 at 02:20
-
@EJP, the BSD man pages are not a standard :-) However, if you can actually cite the Posix stuff that states all data is transferred in blocking mode, I'll be happy to defer. Nothing on the Posix send() page seems to indicate this and the fact that it actually returns a number rather than a boolean value opens up the possibility that it may return less than desired. It also states that it works the same as write() where the flags are zero and write() can *definitely* return less. – paxdiablo Feb 28 '16 at 02:28
-
Specifically for non-pipe/FIFO fds: If the O_NONBLOCK flag is set, write() shall not block the thread. **If some data can be written without blocking the thread, write() shall write what it can and return the number of bytes written.** – paxdiablo Feb 28 '16 at 02:33
Well, there is always the case where you passed in zero as the number of bytes to send... in that case, "returning the number of bytes sent" would indicate that it should return zero bytes.
Probably best to handle the returns-zero case properly anyway; it can't hurt, and it might help.

- 70,199
- 15
- 131
- 234
The answer to this may well be implementation dependent and therefore vary based on the operating system.
One circumstance where 0 would be expected, when you request a transmission of 0 bytes.

- 5,684
- 21
- 25
-
actually, it's not implementation-dependent. it's very possible that you may have asked to send something while the receiving TCP's receive window is full or while the sending TCP's send buffer is completely full. In those sorts of cases, send() could easily return zero. – Chris Cleeland Apr 03 '11 at 20:24
-
2In those cases send() would either block until space is available (and then return some value greater than zero), or if the socket is in non-blocking mode, it would return -1/EWOULDBLOCK – Jeremy Friesner Oct 17 '18 at 16:54
The BSD man page states:
If no messages space is available at the socket to hold the message to be transmitted, then send() normally blocks, unless the socket has been placed in non-blocking I/O mode.
The Posix specification goes further and states that in blocking mode all data is transferred, unless an interrupt occurs.
In both cases zero cannot be returned unless the count supplied was zero.

- 305,947
- 44
- 307
- 483
-
Could an an interrupt occur before the first transfer, thus zero bytes sent? – chux - Reinstate Monica Apr 30 '23 at 23:34
I do observe a zero return from the send(2)
on an AF_UNIX
type socket right now.
Yepp, it was due to the size
field of zero value.
So, JFYI.

- 997
- 1
- 10
- 18
send
returns 0 when you send(socket, buf, 0, 0)
I'd like to provide simple code for others to test.
Server:
In one terminal:
nc -l localhost 10086
Client:
In another terminal:
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
int create_socket()
{
addrinfo hints = {};
addrinfo* servinfo;
int sockfd = -1;
int rv;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
if ((rv = getaddrinfo("localhost", "10086", &hints, &servinfo)))
{
printf("getaddrinfo failed: %s\n", gai_strerror(rv));
exit(1);
}
for(auto p = servinfo; p; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
perror("socket");
continue;
}
else
{
if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
close(sockfd);
perror("connect");
continue;
}
else
puts("client: connected");
}
break;
}
freeaddrinfo(servinfo);
return sockfd;
}
void client()
{
int socket = create_socket();
if(socket == -1)
{
puts("no good");
exit(1);
}
char buf[100] = {0};
while(1){
int ret = send(socket, buf, 0, 0);
if (ret == 0){
printf(".");
}else{
printf("xxxxxxx\n");
}
}
}
int main()
{
setvbuf(stdout, NULL, _IONBF, 0);
client();
return 0;
}
g++ -g -Wall -o send_zero_bytes send_zero_bytes.cpp
./send_zero_bytes

- 7,007
- 2
- 49
- 79