EAGAIN on recv()

10,826

Solution 1

EAGAIN means there is no data available for reading on a non-blocking socket. So, you should run the recv call again.

You haven't actually posted enough code to suggest there is a programming fault, although can I ask if when you detect the connection is closed that you also close down your end as well before re-establishing everything?

Solution 2

Is your socket open in O_NONBLOCK mode? You can check like this:

int flags = fcntl(fd, F_GETFD);
if ((flags & O_NONBLOCK) == O_NONBLOCK) {
  fprintf(stderr, "Yup, it's nonblocking");
}
else {
  fprintf(stderr, "Nope, it's blocking.");
}

In nonblocking mode, recv will return immediately with errno set to EAGAIN if there is nothing to receive yet.

Share:
10,826
user586832
Author by

user586832

Updated on June 04, 2022

Comments

  • user586832
    user586832 almost 2 years

    I implented a socket client to communicate to an ip camera with RTSP over HTTP to get teh video from the camera.

    To stablished the communication with the camera, first i have to set an HTTP-GET tunnel, then send the RTSP commands. When the camera loses the connection, the program has to close the tunnel handler, finish the thread and when the process return to the main function, it begins the communication (start the treads, and so on).

    On the reconnection: the http-get tunnel is set ok, i mean, the socket connects and receives a "HTTP OK", so the program sends a RTSP "DESCRIBE" but the recv always return an EAGAIN error. I check with wireshar that the DESCRIBE OK response is sent from the camera, but the recv never gets it.

    Here is the code:

       struct sockaddr_in aServer;
      // string myData;
      char *myData=new char [256];
      connection *c=(connection*)vargp;
    
    
       memset(&aServer, 0, sizeof aServer);
       aServer.sin_family = AF_INET;
    
       aServer.sin_addr.s_addr = inet_addr(c->theServer.c_str());
       if (aServer.sin_addr.s_addr == INADDR_NONE)
       {
         struct hostent *hp;
    
         hp = gethostbyname(c->theServer.c_str());
         if (hp != NULL)
         {
           memcpy(&aServer.sin_addr, hp->h_addr, hp->h_length);
           aServer.sin_family = hp->h_addrtype;    //Protocol family
         }
         else
               cout << "Failed to resolve " << c->theServer.c_str()  << ": " << hstrerror(h_errno) << endl;
       }
    
       aServer.sin_port = htons(c->thePort);
       c->fd_get = socket(AF_INET, SOCK_STREAM, 0);
    
       struct timeval timeout;
    
       timeout.tv_sec = 5;
       timeout.tv_usec = 0;
    
      setsockopt(c->fd_get, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
    
       if (c->fd_get < 0){
        cout << "fd_get < 0"  << endl;
          c->bFin=true;
          c->WakeUP();
          }
       if (connect(c->fd_get, (struct sockaddr *) &aServer, sizeof aServer) < 0){
        cout << "connect fd_get < 0"  << endl;
        c->bFin=true;
        c->WakeUP();
       }
       if(!c->bFin){
    
        sprintf(myData, "GET %s HTTP/1.1\r\n", c->theURI.c_str());
        sprintf(myData, "%sx-sessioncookie: %s\r\nAccept: application/x-rtsp-tunnelled\r\nAuthorization: %s\r\n\r\n", myData,c->theHTTPSessionId.c_str(), c->addAuthorization(c->aGlobalUsername, c->aGlobalPassword).c_str() );
    
        cout << myData << endl;
        write(c->fd_get, myData, strlen(myData));
    
        //LISTENING...
        int theLen=1500; //3000;
        int ret=0;
        unsigned char datosRecibidos[3000];
    
        int flags =fctl(c->fd_get, F_GETFD;
        if((flags & O_NONBLOCK) == O_NONBLOCK){
            fprint(stderr, "yup, its nonblocking");
        }
        else{
            fprint(stderr, "nope, its blocking");
        }
    
    
        while (c->bFin==false){
    
         ret = read(c->fd_get, ReceivedData, theLen);
        // ret= recvfrom(c->fd_get, ReceivedData, theLen, 0,  (struct sockaddr *) 0, (socklen_t*)0);
         if (ret == 0)
         {
          cout << "Server closed connection: 0" << endl;
    
        }
          else
          if (ret == -1){
         fprintf (stderr, "\n[%d]: %s %d\n", __LINE__, strerror (errno), errno);
    
         if(errno==107 ||errno==EAGAIN){
          cout << "errno" << endl;
          c->bFin=true;
          c->WakeUP();
          cout << "vuelta wakeUP" << endl;
          break;// empezar de nuevo
         }else{
          cout << "errno" << endl;
    
         }
    
        }
        else{
         //cout << (string)ReceivedData[0]<< endl;
         c->ProcessReceivedData(ReceivedData, ret);
         usleep(10);
        }
       }
    
       close(c->fd_get);
       c->fd_get = -1;
    
       }
    

    Could it be a timeout problem? or a stack problem? How can i solve it?

    Thanks in advance for your help. Best regards.

    cristina

  • user586832
    user586832 over 13 years
    Hello, Thanks for your reply! I get "Nope, it's blocking" do you recommend me to set it as non blocking mode? I have complete my first post to complete the code
  • user586832
    user586832 over 13 years
    Hello, I have completed the code it seems that the code is blocking... I also trying setting a loop so the function waits for data but it always received -1. What can i try? Thanks for your help!!
  • hookenz
    hookenz about 13 years
    You're right. Sockets are blocking by default. You have though set a receive timeout. i.e. setsockopt(c->fd_get, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); . Since you get -1 on recv it means there was some sort of error (or timeout!) you then need to check errno variable.