EAGAIN
OR EWOULDBLOCK
gets returned when the socket is in non-blocking mode.
You're probably initializing your socket somewhere with a call to fnctl
and the O_NONBLOCK
flag (or similar effect). Or you are using the MSG_DONTWAIT
flag with the send
call.
In any case, if you don't want to convert the socket back to blocking mode, just invoking the send in a loop should suffice. Regardless of how the socket was initialized (blocking or non-blocking), I always recommend using a loop for the scenario where send
indicates only part of the buffer was handled.
int remaining = <bytes to send>;
int sent = 0;
const char* buffer = <data buffer to send>;
int success = 0;
while (remaining > 0 && !DoesTheAppNeedToExit())
{
int result = send(s, buffer+sent, remaining, 0);
if (result != -1)
{
// sent partial or all the remaining data
sent += result;
remaining -= result;
if (remaining <= 0)
{
success = 1;
break;
}
}
else
{
int err = errno;
if ((err == EAGAIN) || (err == EWOULDBLOCK))
{
timeval tv = {};
fd_set fds = {};
int selectresult;
tv.tv_sec = 1; // or how ever long you want to wait
FD_ZERO(&fds);
FD_SET(0, &fds);
selectresult = select(s+1, NULL, &fds, NULL, &tv);
// recommended: check return value from select and check for fatal error. Or timeout handling.
// socket is ready if IS_FDSET(s, &fds), but it doesn't hurt to just try the send again at this point
}
else
{
// unrecoverable error!
close(s);
s = -1;
break;
}
}
}