2017-10-10 1 views
0

以下のコードに何か間違いがありますが、クライアント接続を使用できないようで、selectステートメントと組み合わせて非ブロック化しているようです。以下のエラー処理の不足を無視してください。BSDソケットconnect + select(クライアント)

私は2つの問題を抱えているようです。1.インターネットサーバー上のポート80に接続しようとすると、ブロックがブロックされます。 2. 127.0.0.1上の既存のポートまたは既存のポートを常に瞬時に返します。成功するか失敗するかを区別することができない選択。

selectと組み合わせてBSDノンブロッキングの理解に欠けているものは何ですか?つまり、それは進行中です:合法的に -

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

errnoconnectにあなたの元の試みに設定されています。その後、selectに電話してください。 selectになっていないため、errnoはリセットされていません。システムコールは、失敗した場合にのみerrnoを設定します。彼らは成功するとそれをクリアしません。

connectが正常に完了している可能性があります。あなたはそれを確認していません。 getsockoptへの呼び出しをSO_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

優秀な回答!ありがとうGil! –

関連する問題