que - socket en c++ cliente servidor linux
En una conexión de socket no bloqueada, select() siempre devuelve 1 (2)
Tengo este segmento de código que está diseñado para conectarse a un servidor usando 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?
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;
}
Un problema que veo es que te pegas en el fdset antes de haber creado el zócalo. Tienes que hacer el
FD_SET(s, &fdset);
después de haber creado el socket porque s es solo un entero y por lo tanto no será el valor correcto hasta después de la llamada a socket ().
EDITAR
Me gusta esto:
.
.
.
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
fd_set *
verificar si el socket está listo para escribir (el segundo argumento fd_set *
para seleccionar), no leer (el primero).