2013-06-12 1 views
1

У меня есть проблема с этим кодом:выбрать для тайм-аута через TCP сокет

FD_ZERO(&cset); 
FD_SET(s, &cset); 

tval.tv_sec = TIMEOUT; 
tval.tv_usec = 0; 

n = select(FD_SETSIZE, &cset, NULL, NULL, &tval); 

if (n==-1) { 
    printf(" select() failed \n"); 
    exit(-1); 
} 
if (n>0) { 
    check_control = connect(s,(struct sockaddr*) 
    &indirizzo_remoto,sizeof(indirizzo_remoto)); 

    if (check_control == -1) { 
     printf("Errore connect()\n"); 
    } 

}else{ 
    printf("Timeout. I'll shutdown the client"); 
    exit(-1); 
} 

Я хочу вставить тайм-аут для подключения, но он не работает:

Я использую правильный IP-адрес и номер порта сервера, но соединение переходит к таймауту.

Большое спасибо за помощь.

+0

Да, с телнет это работает! – user2467899

+0

Это неправильно? Поскольку я хочу, чтобы это был сервер, когда клиент пытается подключиться к нему, если он занимает 30 секунд, клиент остановится и закроет сокет – user2467899

+0

(извините за английский) ....: Я хочу, чтобы если сервер/когда клиент попытается подключиться к нему – user2467899

ответ

2

Вы используете select(), чтобы проверить, является ли данный сокет находится в читаемом состояния перед вызовом connect() на тот же сокет. Это никогда не сработает. Несвязанный TCP-сокет никогда не будет в читаемом состоянии и не может использоваться с select() до тех пор, пока в нем не будет вызван connect().

Единственный способ реализации тайм-аут для connect() вызова поместить гнездо в неблокирующем режиме первого (сокеты блокировки по умолчанию), а затем вызвать connect() (который возвращает EINPROGRESS ошибку, если сокет пытается подключиться), а затем используйте select(), чтобы дождаться, когда сокет введет состояние , доступное для записи, с сообщением об успешном завершении соединения или с ошибкой , указывающей, что соединение не выполнено.

Попробуйте это:

fcntl(s, F_SETFL, O_NONBLOCK); 

Или:

flags = 1; 
ioctl(s, FIOBIO, &flags); 

В зависимости от используемой платформы.

Тогда:

check_control = connect(s, (struct sockaddr*) &indirizzo_remoto, sizeof(indirizzo_remoto)); 
if (check_control == -1) 
{ 
    if (errno != EINPROGRESS) 
    { 
     printf("Errore connect()\n"); 
     exit(-1); 
    } 

    FD_ZERO(&wset); 
    FD_SET(s, &wset); 

    FD_ZERO(&eset); 
    FD_SET(s, &eset); 

    tval.tv_sec = TIMEOUT; 
    tval.tv_usec = 0; 

    n = select(s+1, NULL, &wset, &eset, &tval); 
    if (n == -1) 
    { 
     printf(" select() failed \n"); 
     exit(-1); 
    } 

    if (n == 0) 
    { 
     printf("Timeout. I'll shutdown the client"); 
     exit(-1); 
    } 

    if (FD_ISSET(s, &eset)) 
    { 
     printf("Cannot connect. I'll shutdown the client"); 
     exit(-1); 
    } 

    int err = -1; 
    getsockopt(s, SOL_SOCKET, SO_ERROR, &err, sizeof(err)); 
    if (err != 0) 
    { 
     printf("Cannot connect. I'll shutdown the client"); 
     exit(-1); 
    } 
} 

// connected... 
Смежные вопросы