Configuración del tiempo de espera para la conexión de la función TCP () progtwigción de socket en C saltos recv ()

En mi progtwig Si el servidor no está disponible, la función de conexión demora demasiado tiempo. Así que trato de dar tiempo de espera para conectar utilizando select (). Ahora el problema es que cuando trato de recibir datos del servidor usando recvfrom () obtengo el error “EAGAIN”. Aquí está el código utilizado para conectar y recibir datos del servidor.

int sock; struct sockaddr_in addr; int connectWithServer { int status; struct timeval timeout; timeout.tv_sec = 10; timeout.tv_usec = 0; addr.sin_port = htons(port); sock = socket (AF_INET,SOCK_STREAM,0); inet_pton(AF_INET,serverIP,&addr.sin_addr); fd_set set; FD_ZERO(&set); FD_SET(sock, &set); fcntl(sock, F_SETFL, O_NONBLOCK); if ( (status = connect(sock, (struct sockaddr*)&addr, sizeof(addr))) == -1) { if ( errno != EINPROGRESS ) return status; } status = select(sock+1, NULL, &set, NULL, &timeout); return status; } long int receiveResponse (void *response , unsigned int length) { socklen_t sockLen = sizeof(struct sockaddr); long int received = recvfrom(sock, response, length, 0,(struct sockaddr *)&addr, &sockLen); printf("Received %ld bytes... err %d\n",received, errno); return received; } 

La configuración del tiempo de espera para la función de conexión () tcp socket progtwigción en C no funciona

Corrección. La configuración del tiempo de espera de conexión está funcionando. Lo que ‘no funciona’ es el recvfrom() posterior, y eso se debe a que dejó el socket en el modo de no locking y no sabe qué hacer con el EAGAIN. resultante EAGAIN. Entonces, manéjelo, utilizando select() para decirle cuándo el zócalo está listo para leer, o bien, vuelva a poner el zócalo en modo de locking después de finalizar la conexión.

La primera selección exitosa significa que la operación de conexión está completa, pero no necesariamente significa que tenga éxito , desde la página de SO_ERROR man, debe verificar SO_ERROR para asegurarse de que se completó correctamente

Es posible seleccionar (2) o sondeo (2) para completar seleccionando el zócalo para escribir. Después de que select (2) indica capacidad de escritura, use getsockopt (2) para leer la opción SO_ERROR en el nivel SOL_SOCKET para determinar si connect () se completó correctamente (SO_ERROR es cero) o no tuvo éxito (SO_ERROR es uno de los códigos de error habituales que se enumeran aquí, explicando el motivo del fracaso).

Así que en tu código deberías hacer algo como esto:

 int ret; ret=select(sockfd+1, NULL, &wfds, NULL, NULL); //should use timeout if(ret==1 && getSocketOpt(sockfd, SO_ERROR) ==0) { return 0; //successfully connected } 

Luego, como se mencionó en la otra respuesta, debe llamar a seleccionar nuevamente antes de escribir o leer desde el socket.

Recibe EAGAIN porque no hay datos para leer del búfer de socket y su socket se configuró como no nonblocking . Como no estás conectado con el compañero, no me sorprende.

Mira esto desde el man recvfrom

Si no hay mensajes disponibles en el zócalo, las llamadas de recepción esperan a que llegue un mensaje, a menos que el zócalo no esté bloqueando (consulte fcntl (2)), en cuyo caso se devuelve el valor -1 y la variable externa errno se establece en EAGAIN. Las llamadas de recepción normalmente devuelven cualquier dato disponible, hasta la cantidad solicitada, en lugar de esperar la recepción de la cantidad total solicitada.

Otro caso podría ser el siguiente:

  • Su zócalo puede estar conectado pero está comprobando demasiado rápido si se recibe algo. Para evitar esto, haga otra selección antes de recuperar para extraer el paquete del búfer de socket (llamando a readfrom o simplemente a read ) solo cuando esté seguro de que recibió algo.

El zócalo debe configurarse en modo de locking nuevamente antes de llamar a recv ().

 fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) & ~O_NONBLOCK);