How to avoid 'No buffer space available' on C socket?

Hello everybody,

Years ago i left in stand-by a project of mine where the main program was supposed to send thousands ARP frames over the socket as fast as it could; but because of a programming issue i couldn't continue it.

2 days ago I decided to solve that issue.

The thing is, when the program sends bunch of data, eventually it gives the error "No buffer space available". I increased the buffer space size and it gave more sending time, but it gave the same error message later. My question is, Is there a way to send bunch of data, fast and avoiding this socket error? I don't know, by freeing it, cleaning it, etc.

I'll appreciate any help, and please excuse my poor english.
Thank you.

Here's part of the code:

unsigned int buff;
socklen_t optlen;
optlen = sizeof(buff);
...
struct sockaddr sockaddr;
struct ifreq ifreq;

memset(&ifreq, 0, sizeof(ifreq));
strcpy(sockaddr.sa_data, device); /* Transmitting device is set. */
strcpy(ifreq.ifr_name, device);

if((sock = socket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ALL))) < 0)
        {
        perror("socket()");
        exit(-1);
        }
if((setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof(ifreq))) < 0)
        {
        perror("setsockopt() cannot bind.");
        exit(-1);
        }

if((resource=getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buff, &optlen))<0)
{
perror("getsockopt()");
}

printf("Attempting to increase SNDBUF... ");
buff = 2147483647; /*MAXIMUM*/

if((resource = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buff, 
sizeof(buff)))<0)
{
perror("setsockopt()");
} 

/*HERE'S THE TRANSMITTING PART*/

            time_t startTime;
            startTime = time(NULL);

        while(time(NULL) - startTime < (time_assigned * 60))
        {
    azimuth++;
    printf("%u\n", (unsigned int )azimuth);        
    ret= sendto(sock, &arpmsg, sizeof(struct arpmsg),0, &sockaddr,sizeof(sockaddr));

    if(ret < 0 && ret != ENOBUFS) 
        {
        perror("sendto()");
        exit(-1);
        }
        checkordersarrival();
        }

Do you have code for the server program as well...if so post it here and what kind of socket are you creating a local or network socket...

It's not hard for a program to fill a buffer far faster than your network can send data. That is why you're running out of buffer. You'll just have to trust the OS to send the data as fast as it can, unless you feel like writing your own driver.

And isn't there a way to avoid this? I don't know... Increasing socket sending time or reducing it by SO_RCVTIMEO or SO_SNDTIMEO.

I don't care if my program has to hang a little bit between sending blocks, I just don't want it to close because of the socket error.

---------- Post updated at 06:34 PM ---------- Previous update was at 05:21 PM ----------

Corona688, You gave me the answer... TIME.

If my socket overloads its buffer it crashes, so, I solved it giving it time in this way:

while(time(NULL) - startTime < (time_assigned * 60))
{
 retry: /*This is a label.*/
 ret = sendto(sock, &arpmsg, sizeof(struct arpmsg),0, &sockaddr,sizeof(sockaddr));

    if(ret < 0) 
        {
           if(errno == ENOBUFS)
            {
              printf("Socket ran out of buffer space.\n");
              printf("Giving it some time...\n");
              usleep(300000);
              goto retry;
             }else {
                       perror("sendto()");
                       exit(-1);
                       }
         }
        checkordersarrival();
        }
}

So, if my socket runs out of buffer space while sending, it waits some nsecs, and then goes to the label where it retries to send the message. I don't know if this ain't the best way to avoid it, but keeping it simple, It works!.

Thanks everybody for your help!
As always, the best place on the Internet to ask for a good programming advice is here. :b:

Usually you would leave the socket as blocking, so that when the buffer fills, your program waits. If you can't trust the OS to transmit as fast as possible, then you're stuck either way, since you can't not use the OS...