2017-10-10 56 views
0

下面的代碼中必須有錯誤,但我似乎無法使用客戶端連接,非阻塞與select語句結合使用。請忽略以下缺少錯誤處理。BSD套接字連接+選擇(客戶端)

我似乎有兩個問題 1.選擇阻塞,直到超時(60)如果我嘗試連接互聯網服務器的80端口 2.嘗試將現有的或不存在的端口連接127.0.0.1總是立即返回選擇無法區分連接成功或失敗。

我在理解BSD非阻塞與select的結合中所缺少的是什麼?

fd_set readfds; 
FD_ZERO(&readfds); 

struct timeval tv; 
tv.tv_sec = 60; 
tv.tv_usec = 0; 

struct sockaddr_in dest; 
int socketFD = socket(AF_INET, SOCK_STREAM, 0); 

memset(&dest, 0, sizeof(dest)); 
dest.sin_family = AF_INET; 
dest.sin_addr.s_addr = inet_addr("127.0.0.1"); 
dest.sin_port = htons(9483); 

long arg; 
arg = fcntl(socketFD, F_GETFL, NULL); 
arg |= O_NONBLOCK; 
fcntl(socketFD, F_SETFL, arg); 

if (connect(socketFD, (struct sockaddr *)&dest, sizeof(struct sockaddr))<0 && errno == EINPROGRESS) { 

    //now add it to the read set 
    FD_SET(socketFD, &readfds); 
    int res = select(socketFD+1, &readfds, NULL, NULL, &tv); 

    int error = errno; 
    if (res>0 && FD_ISSET(socketFD, &readfds)) { 
     NSLog(@"errno: %d", error); //Always 36 
    } 
} 

回答

1

errno在你原來的嘗試設置爲connect - 合法:即是,它正在進行。您然後致電select。由於select沒有失敗,因此errno未被重置。系統調用失敗時僅設置errno;他們沒有成功清除它。

connect可能已成功完成。你雖然沒有檢查。您應該添加一個電話getsockoptSO_ERROR以確定它是否工作。這將在套接字上返回錯誤狀態。

另一個重要說明。根據手冊頁(https://www.freebsd.org/cgi/man.cgi?query=connect&sektion=2),您應該使用writefds來等待完成connect。我不知道readfds是否會正確報告狀態。

[EINPROGRESS] The socket is non-blocking and the connection cannot 
       be completed immediately. It is possible to select(2) 
       for completion by selecting the socket for writing. 

另請參閱這個非常類似的問題。 Using select() for non-blocking sockets to connect always returns 1

+0

優秀的答案!謝謝吉爾! –

相關問題