2014-10-08 134 views
0

我試圖解決使用select()從套接字超時問題讀取數據。不幸的是,這個函數在被調用後立即返回-1。什麼可能是錯的?select()在從套接字讀取時返回-1

commStatus communicate(const char * tx, char * rx, const int bufSize , const char * inetAddr, const int port) 
{ 

    commStatus r; 
    if (!sockInitialised) initSock(); 

    if (sockInitialised) 
    { 
     SOCKET s; 
     struct sockaddr_in server; 

     server.sin_addr.s_addr = inet_addr(inetAddr); 
     server.sin_family = AF_INET; 
     server.sin_port = htons(port); 

     if((s = socket(AF_INET , SOCK_STREAM , 0)) == INVALID_SOCKET) 
     { 
      std:stringstream d; d <<"Could not create socket : " << WSAGetLastError(); 
      LogIt(d,Level::Error); 
     } else 
     { 
      if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0) 
      { 
       puts("connect error"); 
       r= commStatus::COMM_NO_TRANSMIT ; 
      } else 
      { 
       int l =strlen(tx)+strlen("DATA "); 

       char* dtx ; 
       dtx = (char*) calloc(sizeof(char),strlen(tx)+strlen("DATA ") + 1); 

       sprintf(dtx,"DATA %s",tx); 

       if(send(s , dtx , strlen(dtx) , 0) < 0) 
       { 
        puts("Send failed"); 
        r= commStatus::COMM_NO_TRANSMIT; 
       } else 
       { 

        int recv_size = 0; 


        struct timeval selTimeout; 
        selTimeout.tv_sec = 20;  /* timeout (secs.) */ 
        selTimeout.tv_usec = 0;   /* 0 microseconds */ 
        fd_set readSet; 
        FD_ZERO(&readSet); 
        #define STDIN_FILENO 0 
        FD_SET(STDIN_FILENO, &readSet);//stdin manually trigger reading 
        FD_SET(s, &readSet);//tcp socket 
        int numReady = select(s+1, &readSet, NULL, NULL, &selTimeout); 


        if(numReady > 0) 
        { 
         if((recv_size = recv(s , rx , bufSize ,0)) == SOCKET_ERROR) 
         { 
          r= commStatus::COMM_NO_RECEIVE; 
         } else 
         { 
          rx[recv_size] = '\0'; 
          r= commStatus::COMM_OK; 
         } 
        } else r=commStatus::COMM_NO_RECEIVE; 
       } 
       free(dtx); 
      } 
     } 
    } else r= commStatus::COMM_NO_TRANSMIT; 
return r; 

} 
+0

你選擇返回-1後,你試過調用'WSAGetLastError()'嗎?它返回什麼? – Hasturkun 2014-10-08 10:34:42

回答

0

據我所知,你試圖通過stdin Winsock的select()函數。

不幸的是,在Windows下,select()只接受套接字句柄,而不是通用文件描述符。

如果您打電話給WSAGetLastError(),您可能會看到它返回WSAENOTSOCK

+0

這正是我錯誤的 - WSAENOTSOCK。我評論過FD_SET(STDIN_FILENO,&readSet);線。但現在選擇立即返回1,但尚未提供接收數據。 – vico 2014-10-08 12:54:21

0

在C,您可以檢查errno變量,它應該告訴你,你所造成的誤差具體問題

或者,你可能有perror()功能,這將給你一個可讀的版本:

#include <stdio.h> 
: 
perror ("select"); 

如果你是下的Windows,WSAGetLastError()將作爲errno可變的,this page捐贈可能性和解釋:

WSANOTINITIALISED - 成功在使用此功能之前必須進行全面的WSAStartup調用。

WSAEFAULT - Windows Sockets實現無法分配所需的資源用於其內部操作,或readfds,writefds,exceptfds,或timeval中的參數不是用戶地址空間的一部分。

WSAENETDOWN - 網絡子系統失敗。

WSAEINVAL - 超時值無效,或者所有三個描述符參數均爲空。

WSAEINTR - 阻塞的Windows Socket 1.1調用通過WSACancelBlockingCall取消。

WSAEINPROGRESS - 阻塞的Windows套接字1.1調用正在進行中,或者服務提供程序仍在處理回調函數。

WSAENOTSOCK - 其中一個描述符集包含一個不是套接字的條目。

+0

Asker似乎在使用winsock,在這種情況下'select()'不會設置'errno',而是通過'WSAGetLastError()'返回一個錯誤。 – Hasturkun 2014-10-08 10:36:01

+0

@Hasturkun:是的,在我看到MSVC標籤後才編輯。 – paxdiablo 2014-10-08 10:37:00