2011-06-07 25 views
1

iOSシミュレータ(おそらくMacとFreeBSDと同じTCPスタックを使用)からのループバックアドレスに非ブロッキング接続を行うと、サーバープロセスが実行されていなくても常に成功します。ループバックアドレス(127.0.0.1またはlocalhost)にノンブロッキング接続

タイムアウトがゼロのselect()を使用して接続が成功したことを検出しました。したがって、select()が0を返す限り、接続が進行中であると仮定します。-1を返した場合はエラーが発生し、1が返された場合はソケットが読み込み可能になります(サーバが応答したはずです)私は、接続が成功したことを報告した後に読み始めます。

これは、ループバックを除くすべてのアドレスで正常に動作します。ループバックでは、サーバーが実行されていない場合でも、select()は常に1を返します。だから、私は読んで始めます。失敗すると私はそれを処理します。しかし、私はselect()を使ってこれを検出したはずです!

答えて

0

問題は、接続が成功したかどうかを私に知らせるためにselect()に依存していたことでした。 Selectは、そのfdで何か変更されたかどうかだけを通知します。ソケット上で実際にconnect()をもう一度呼び出す必要があり、失敗した場合、errnoはEINPROGRESS、ECONNまたはEALREADYのいずれかであることを確認する必要があります。 ECONNを除いて、他のすべての値は再試行する必要があることを意味します。 ECONNは既に接続されていることを意味します。それ以外のerrno値は、接続に失敗したことを意味します。

3

の前には、の直前に、connect()というエラーが表示されます。 select()に進む前に、errnoEINPROGRESSであることを確認してください。 * BSDでは、localhostエラーの非リスニングポートへの接続(またはエラー)が直ちに発生します。

私はちょうどこのような非常に簡単なテスト(ヘッダをスキップ)走った:私が得た、ポート9671に聞いて何も

int 
main(void) 
{ 
    int fd; 
    int r; 
    struct sockaddr_in remote; 
    struct hostent *he; 

    he = gethostbyname("localhost"); 
    if (he == NULL) 
      return -1; 

    memcpy(&remote.sin_addr, he->h_addr, sizeof(remote.sin_addr)); 
    remote.sin_port = htons(9671); 
    remote.sin_family = AF_INET; 

    fd = socket(PF_INET, SOCK_STREAM, 0); 
    fcntl(fd, F_SETFL, O_NONBLOCK); 

    r = connect(fd, (struct sockaddr *)&remote, sizeof remote); 
    if (r < 0) { 
      perror("connect"); 
    } 
    return 0; 
} 

を:Linux上

  • を:connect: Operation now in progress
  • FreeBSD上で:connect: Connection refused

もちろん、i s 常にすべてのシステムコールのエラーコードをチェックすることをお勧めします(上記の例は単純化のためではありません。

+0

私は実際にconnect()からEINPROGRESSを取得しています。もう一度確認してお知らせします。 – Plumenator

+0

Yup、EINPROGRESS。 – Plumenator

+0

あなたは 'connect'の結果をチェックしなかったと申し訳ありません。ちなみに、あなたは読書のために選んでいるのですか?少なくともFreeBSDの 'connect(2)'マン・ページは、書き込みのために選択すべきであることを示しているようです。 – Grrrr

関連する問題