I have read the documentation at least 10 times now and have also read some 10 or so code snippets and full programs where non-blocking sockets are used for sending data. The problem is that some of the tutorials are either for beginners (Beejs f.i.) or are pretty sloppy in their assumptions; and those that are not are complicated are specialized code examples that don’t explain why they do what they do. Even SO knowledge base doesn’t exhaustively cover the entire gamut of send behavior, in my opinion. What I am after are details on f.e:
- What does return code of 0 indicate exactly, and is it worth checking
errnothen or should one just discard the connection without further investigation? - Does getting a negative return value warrant closing a connection gone bad, or is it only so unless
errnoisEWOULDBLOCK,EAGAINorEINTR(…others) ? - Is it worth checking
errnowhen return value is> 0? Apparently, the value indicates amount of data “sent” (in quotes because it’s a long process really, right), but since the socket is non-blocking, does it mean one can issue another call right away, or, depending onerrnoagain, one should wait for the next sending occasion (using select/poll/epoll) ? - Basically, does one check the return value first and only then the
errnovalue? Or maybesendsetserrnoon each call, return value regardless? That would make error checking somewhat easier… - If one gets
EINTR, what would be a good, robust behavior for a program to take? Simply record the state and retry on next send occasion, like withEWOULDBLOCKandEAGAIN? - Does one check for both
EWOULDBLOCKandEAGAIN? Can we trust both having the same value, or does it depend on the implementation? - Does
sendreturnEMSGSIZEfor stream sockets? If it doesn’t, then no buffer size is too big, right? - Can return value itself be equal to either of the known error codes?
If you could provide an example of robust non-blocking send code, it would be absolutely appreciated.
A lot of questions here:
On a POSIX system, send(2) can never return 0 unless you call it with a length arg of 0. Check the docs for your specific system to make sure it follows the POSIX spec
No, a -1 return value (the only possible negative return value) just means that no data was sent. You need to check errno to see WHY — see the send(2) man page for a full listing of all the possible errno value and what they mean
If send returns success (> 0), then errno will be unchanged and will contain whatever it had before (which is probably an error from some earlier system call).
Check the return value first and then errno if the return value is -1. If you really want to, you can set errno to 0 before the call and then check it afterwards
Well, the simplest is to disable interruption of system calls, in which case you’ll never get an EINTR. Treating it the same as EWOULDBLOCK/EAGAIN is good too.
Depends on the implementation, though generally they’re the same. Sometimes there’s weirdness with SysV vs BSD emulation modes that might make them different and either might occur
Stream sockets don’t have atomic messages and EMSGSIZE is only for atomic messages, so no, stream sockets can’t return EMSGSIZE
The only error code is -1. Success is the number of bytes written, so if you could write 2^32-1 bytes on a 32-bit machine (or 2^64-1 on a 64 bit machine), it would be a problem, but you can’t write that many bytes (and you’ll generally get a EINVAL or EFAULT if you try).