В неблокирующем соединении сокета select () всегда возвращает 1 - PullRequest
6 голосов
/ 30 апреля 2011

У меня есть этот сегмент кода, который предназначен для подключения к серверу через сокет.Однако, если он не может подключиться к серверу в течение определенного времени, я бы хотел, чтобы он прекратил попытки.Я попытался сделать это с помощью этого неблокирующего сокета и команды select, но select всегда возвращает 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;
}

Ответы [ 2 ]

13 голосов
/ 30 апреля 2011

Вам нужно проверить, готов ли сокет для записи (второй fd_set * аргумент для выбора), а не для чтения (первый).

12 голосов
/ 30 апреля 2011

Одна проблема, которую я вижу, заключается в том, что вы вставляете s в fdset до того, как создаете сокет.Вам нужно сделать

FD_SET(s, &fdset);

после того, как вы создали сокет, потому что s - это просто целое число, и поэтому не будет правильным значением до окончания вызова socket ().

РЕДАКТИРОВАТЬ

Как это:

.
.
.
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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...