2011-04-30 12 views
5

Tengo este segmento de código que está diseñado para conectarse a un servidor mediante una conexión de socket. Sin embargo, si no se puede conectar al servidor dentro de una cierta cantidad de tiempo, me gustaría que dejara de intentarlo. Intenté hacer esto con este socket no bloqueante y el comando select, pero siempre seleccioné return 1 indicando que el servidor existe cuando no existe nada en la dirección que le doy. ¿Algunas ideas?En una conexión de socket no bloqueada, select() siempre devuelve 1

SOCKET tcp_client(char *hname, char *sname) {  
    fd_set fdset; 
    struct sockaddr_in peer; 
    SOCKET s; 
    FD_ZERO(&fdset); 
    // FD_SET(STDIN, &fdset); 
    FD_SET(s, &fdset); 
    errno=1; 
    struct timeval tv; 
    tv.tv_sec = 15; 
    set_address(hname, sname, &peer, "tcp"); 
    s = socket(AF_INET, SOCK_STREAM, 0); 

    int n = 1; 
    fcntl(s, F_SETFL, O_NONBLOCK); 

    if (!isvalidsock(s)) 
    { 
     printf("Socket Call Failed: %s\n", strerror(errno)); 
     return(0); 
    } 

    int x = 0; 

    int status = connect(s, (struct sockaddr *)&peer, sizeof(peer)); 

    if(status < 0) { 
     printf("Status: %i\n", status); 
    } 

    int retVal = select(s+1, &fdset, NULL, NULL, &tv); 
    printf("retVal: %i\n", retVal); 

    if (retVal == 1) { 
     int so_error; 
     socklen_t slen = sizeof so_error; 
     getsockopt(s, SOL_SOCKET, SO_ERROR, &so_error, &slen); 
     if (so_error == 0) { 
      printf("work\n"); 

      x =1; 
     } else { 
      printf("fail\n"); 
      x = 0; 
     } 
    } else {  
     printf("noSocks\n"); 
    } 


    if (x ==0) 
    { 
     printf("Connect Failed: %s\n", strerror(errno)); 
     L("libOnexc: Connect to socket failed"); 
     close(s); 
     return(0); 
    } 

    return s; 
} 
+0

Corrija la sangría. ¡Es horrible! –

+0

Bueno, no estoy esperando más de esperar 15 segundos usando select() para ver si se ha conectado, pero siempre está regresando que está conectado cuando no lo está. – Daniel

Respuesta

12

Un problema que veo es que usted se pega en el fdset antes de haber creado el zócalo. Que tiene que hacer el

FD_SET(s, &fdset); 

después de haber creado la toma porque s es un número entero y por lo tanto no va a ser el valor justo hasta después de la llamada a socket().

EDITAR

De esta manera:

. 
. 
. 
SOCKET s; 
errno=1; 
struct timeval tv; 
tv.tv_sec = 15; 
set_address(hname, sname, &peer, "tcp"); 
s = socket(AF_INET, SOCK_STREAM, 0); 

int n = 1; 
fcntl(s, F_SETFL, O_NONBLOCK); 

if (!isvalidsock(s)) 
{ 
    printf("Socket Call Failed: %s\n", strerror(errno)); 
    return(0); 
}  

FD_ZERO(&fdset); 
FD_SET(s, &fdset); // don't put socket in set until it is actually created 
+0

Lo moví después de que se creó el zócalo pero ahora selecciono siempre devuelve 0 incluso cuando trato de conectarme a una máquina que sé que existe ... – Daniel

+0

Gracias a su respuesta combinada con R ... ¡funcionó a la perfección! – Daniel

12

Es necesario comprobar si el zócalo esté listo para la escritura (el segundo argumento fd_set * para seleccionar), no leer (la primera).

+0

¡Gracias a su respuesta combinada con Brian ha funcionado perfectamente! – Daniel

+2

@Daniel Luego dale al chico un +1 ;-) Lo haré por ti. –

+1

No hay problema, ya tengo suficientes +1. :-) –

Cuestiones relacionadas