EAGAIN on recv()
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.
user586832
Updated on June 04, 2022Comments
-
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 over 13 yearsHello, 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 over 13 yearsHello, 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 about 13 yearsYou'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.