Yosef Alon Yosef Alon - 1 month ago 21
C Question

Resource temporarly unavalible - MSG_DONTWAIT flag

I am using tcp socket server and client in c.
Using AF_INET, SOCK_STREAM and IPPROTO_TCP

My send function in client side

sent_now = send(sockId, buffer + sent_total, len - sent_total, MSG_DONTWAIT);


When I send MSG up to size like 20K-40KB, It works fine.
When I send MSG up to size like 365K (Thats what I need), I receive the following error in the server Side: Resource temporarily unavailable!

My receive function in server side

totalRecvMsgSize = recieve ( clntSocket, Buffer, RCVBUFSIZE , MSG_DONTWAIT);

I send int data type.

How can I receive all the array in one send and receive operation?

old post

There is a post What can cause a “Resource temporarily unavailable” on sock send() command, where Davide Berra says that


That's because you're using a non-blocking socket and the output
buffer is full.

From the send() man page

When the message does not fit into the send buffer of the
socket, send() normally blocks, unless the socket has been placed
in non-block- ing I/O mode. In non-blocking mode it would return
EAGAIN in this case.

EAGAIN is the error code tied to "Resource temporarily unavailable"

Consider using select() to get a better control of this behaviours


My question is:

*1) How can I receive all the array in one send and receive operation? *

2) does select() help me in this array size?

3) Can I change the buffer sizes and how?

Answer

Since this is a stream socket, you use a loop on send(), and MSG_WAITALL on recv().

Consider these helper functions:

/* Receive the entire buffer.
 * Returns 0 if success, nonzero errno otherwise.
*/
static int recv_all(const int sockfd, void *buffer, const size_t len)
{
    ssize_t n;

    n = recv(sockfd, buffer, len, MSG_WAITALL);
    if (n == 0)
        return errno = EPIPE; /* Other end will not send more data */
    else
    if (n == -1)
        return errno;
    else
    if (n < -1)
        return errno = EIO;   /* Should never occur */
    else
    if (n != (ssize_t)len)
        return errno = EINTR; /* Interrupted, or sender goofed */
    else
        return 0;
}

/* Send the entire buffer.
 * Returns 0 if success, nonzero errno otherwise.
*/
static int send_all(const int sockfd, const void *buffer, const size_t len)
{
    const char       *pos = (const char *)buffer;
    const char *const end = (const char *)buffer + len;
    ssize_t           n;

    while (pos < end) {

        n = send(sockfd, pos, (size_t)(end - pos), 0);
        if (n > 0)
            pos += n; 
        else
        if (n != -1)
            return errno = EIO;
        else
            return errno;
    }
}