2012-06-19 3 views
4

У меня уже был мой класс сокетов, но я хотел добавить таймаут, используя select(). Кажется довольно прямолинейным, но у меня всегда есть 0, возвращаемый функцией select(). Я даже удалил check(), чтобы он считывал данные независимо от select(), и данные считываются, но select() все еще сообщает, что данных нет. Любая подсказка о том, как получить select(), чтобы перестать лгать мне? Я также установил, что сокет не блокируется. Благодарю.check on socket with select() возвращает 0, когда данные присутствуют

Код:

char buf [ MAXRECV + 1 ]; 

s = ""; 

memset (buf, 0, MAXRECV + 1); 


struct timeval tv; 
int retval; 

fd_set Sockets; 
FD_ZERO(&Sockets); 
FD_SET(m_sock,&Sockets); 

// Print sock int for sainity 
std::cout << "\nm_sock:" << m_sock << "\n"; 

tv.tv_sec = 1; 
tv.tv_usec = 0; 

retval = select(1, &Sockets, NULL, NULL, &tv); 
std::cout << "\nretval is :[" << retval << "]\n\n"; 

// Check 
if (FD_ISSET(m_sock,&Sockets)) 
    std::cout << "\nFD_ISSET(m_sock,&Sockets) is true\n\n"; 
else 
    std::cout << "\nFD_ISSET(m_sock,&Sockets) is false\n\n"; 

// If error occurs 
if (retval == -1) 
{ 
    perror("select()"); 
    std::cout << "\nERROR IN SELECT()\n"; 
} 
// If data present 
else if (retval) 
{ 
    std::cout << "\nDATA IS READY TO BE READ\n"; 
    std::cout << "recv (m_sock, buf, MAXRECV, 0)... m_sock is " << m_sock << "\n"; 
    int status = recv (m_sock, buf, MAXRECV, 0); 

    if (status == -1) 
    { 
     std::cout << "status == -1 errno == " << errno << " in Socket::recv\n"; 
     return 0; 
    } 
    else if (status == 0) 
    { 
     return 0; 
    } 
    else 
    { 
     s = buf; 
     return status; 
    } 
} 
// If data not present 
else 
{ 
std::cout << "\nDATA WAS NOT READY, TIMEOUT\n"; 
return 0; 
} 

ответ

4

Ваш звонок по номеру select неверен, как вы уже обнаружили. Несмотря на то, что первый параметр называется nfds во многих формах документации, он на самом деле является одним из самых больших номеров дескрипторов файлов, хранящихся на любом из fd_set, переданных в select. В этом случае, поскольку вы передаете только в одном дескрипторе файла, вызов должен быть:

retval = select(m_sock + 1, &Sockets, NULL, NULL, &tv); 

Если у вас есть произвольное количество сокетов вы обработки каждого в другом потоке, вы можете найти свой ответ на this question лучший подход.

+0

Да, я полностью согласен, намного лучше. Моя настройка прямо сейчас имеет дело с двумя сокетами, одной синхронизацией и одной асинхронной. Но я вызывающе собираюсь переписать, чтобы реализовать ваш подход. – Matt

0

Упс. Похоже, я забыл установить select() 's int nfds:

теперь работает хорошо.

+0

мои поздравления =) – inkooboo

+1

Это неверно, первый аргумент 'select()' не должен быть 'FD_SETSIZE' вообще, и, в частности, не для этого кода. См. Ответ пользователя315052. – unwind

Смежные вопросы