2014-02-13 16 views
0

我想通過說將我的問題完全解決,方法是通過將Select()的超時選項設置爲NULL來解決問題。Winsock - 選擇在偵聽套接字上的超時導致每個後續的Select呼叫失敗

但我想使用超時,所以這是我的問題。服務器程序非常簡單,它監聽連接,接受它們並打印到控制檯。

的問題是,在選擇第一超時後,選擇將返回-1(MSDN小到無的文件給我,什麼會導致-1從選擇(返回),只知道它的錯誤信號),並有效地阻止來自程序的更多通信。

服務器 - main.cpp中

int main(){ 

    /* variables */ 
    int iResult, iSendResult; 
    char recvbuf[DEFAULT_BUFLEN]; 
    int recvbuflen = DEFAULT_BUFLEN; 
    bool exit=false; 
    int foundRoom, tempFoundRoom; 
    fd_set readfds, writefds; 
    struct timeval tv; 
    long double counter=0; 
    int maxfd=0; 

    /* Server variables */ 
    WSADATA wsaData; 
    SOCKET ListenSocket = INVALID_SOCKET; 
    SOCKET ClientSocket = INVALID_SOCKET; 
    struct addrinfo *result = NULL; 
    struct addrinfo hints; 


    printf("~SERVER~\n"); 

    /* Initialize Winsock*/ 
    initialize_winsock(wsaData, hints, &result); 

    /* Set socket and bind to TCP listening socket */ 
    set_socketandbind(ListenSocket, result, maxfd); 

    //non-blocking mode 
    u_long iMode=1; 
    ioctlsocket(ListenSocket,FIONBIO,&iMode); 
    ioctlsocket(ClientSocket,FIONBIO,&iMode); 

    // clear the set ahead of time 
    FD_ZERO(&readfds); 
    //FD_ZERO(&writefds); 

    //add our descriptors to the set 
    FD_SET(ListenSocket, &readfds); 

    //wait until either socket has data ready to be recv()d (timeout 5 secs) 
    tv.tv_sec = 5; 
    tv.tv_usec = 0; 

    /* main loop */ 
    for(;;){ 
     cout << "Maxfd: " << ListenSocket << " \ " << maxfd << endl; 

     //select 
     int rv = select(ListenSocket+1, &readfds, NULL, NULL, &tv); 

     cout << "Updateing... rv: " << rv << endl; 

     if (rv == -1) { 
      perror("Select: "); // error occurred in select() 
     }else if (rv == 0){ 
      printf("Timeout occurred! No data after 5 seconds.\n"); 
     }else{ 

      // one or both of the descriptors have data 
      if (FD_ISSET(ListenSocket, &readfds)) { 

       // Accept a client socket 
       ClientSocket=accept(ListenSocket, NULL, NULL); 

       cout << "Connected a user." << endl; 

      } 

      counter++; 
     } 

     cout << endl; 
     Sleep(500); 

    }; 

    /* Unset server socket */ 
    closesocket(ListenSocket); 

    system("pause"); 
    return 0; 
} 

輸出應該是超時,超時,超時,因爲多數民衆贊成應該如何選擇()的工作,以及它是如何工作的我的客戶端上。相反,輸出是超時,錯誤,錯誤,錯誤:

enter image description here

回答

4

您需要重置「TV」和FD結構周圍循環每次。

+0

你的意思是每次select()被調用時,都會重置電視結構? –

+0

這實際上並不能解決問題。我需要添加FD_ZERO和FD_SET並在循環中重置電視,不僅在每個循環中添加電視。爲什麼是這樣? –

+1

因爲select()更改FD結構。如果你有超時時間,沒有準備好,所以相應的位被清除了,所以你需要重置它。 – EJP