2012-06-19 94 views
4

我已經讓我的套接字類工作了一段時間,但我想用select()添加一個超時。看起來很簡單,但我總是從select()返回0。我甚至刪除了select()檢查,因此無論select()如何讀取數據並且讀取數據,但select()仍報告數據不存在。有關如何讓select()停止對我說謊的線索?我也將套接字設置爲非阻塞。謝謝。使用select()檢查socket時數據存在時返回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,但它實際上比傳遞給selectfd_set中的任何一個所保存的最大文件描述符編號都多一個。在這種情況下,因爲你只傳遞一個文件描述符,調用應該是:

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

如果您在不同的線程處理每個插座的任意號碼,你可能會發現我的回答this question一個更好的方法。

+0

是的,我完全同意,好多了。我現在的設置是處理2個套接字,一個同步和一個異步。但我敢肯定要重寫來實現你的方法。 – Matt

0

哎呦。看起來我忘了設置select()的int nfds:

現在運行良好。

+0

my congratulations =) – inkooboo

+1

這是錯誤的,'select()'的第一個參數一般不應該是'FD_SETSIZE',特別是不適用於這個代碼。請參閱user315052的答案。 – unwind

相關問題