2009-08-08 11 views
1

私はクロスプラットフォームのフレームワークでソケットレイヤーを再生していますが、接続をノンブロッキングで動作させようとしています。しかし、ドキュメントの上に注いだ後、彼らはまったく正しく動作していないように見えます。問題の中心は、非ブロッキング接続を開始した後、次の選択が失敗して接続が成功し、何度も何度もタイムアウトし続けることです。私が選択した後、「RET> 0」の条件を削除するとノンブロッキング接続で不正なMacOSX select()ビヘイビア

Initial connect = -1 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1001 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 
0 = select(0,1,0) errno=0 time=1000 

次の接続が成功したとリターン:私はMacOSXのの最新のLeopardビルドでこのコードを実行すると

SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
hostent *h = gethostbyname("www.memecode.com"); 
if (h) 
{ 
    sockaddr_in addr; 
    memset(&addr, 0, sizeof(addr)); 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons(80); 

    if (h->h_addr_list && h->h_addr_list[0]) 
    { 
     memcpy(&addr.sin_addr, h->h_addr_list[0], sizeof(in_addr)); 

     // Set non blocking 
     fcntl(s, F_SETFL, O_NONBLOCK); 

     int64 start = LgiCurrentTime(); 
     int status = connect(s, (sockaddr*) &addr, sizeof(sockaddr_in)); 
     printf("Initial connect = %i\n", status); 
     while (status && (LgiCurrentTime()-start) < 15000) 
     { 
      // Do select to wait for connect to finish 
      fd_set wr; 
      FD_ZERO(&wr); 
      FD_SET(s, &wr); 
      int TimeoutMs = 1000; 
      struct timeval t = {TimeoutMs/1000, (TimeoutMs % 1000) * 1000}; 
      errno = 0; 
      int64 sel_start = LgiCurrentTime(); 
      int ret = select(0, 0, &wr, 0, &t); 
      int64 sel_end = LgiCurrentTime(); 
      printf("%i = select(0,%i,0) errno=%i time=%i\n", 
       ret, 
       FD_ISSET(s, &wr)!=0, 
       errno, 
       (int)(sel_end-sel_start)); 

      if (ret > 0 && FD_ISSET(s, &wr)) 
      { 
       // ready for connect to finish... 
       status = connect(s, (sockaddr*) &addr, sizeof(sockaddr_in)); 
       printf("2nd connect = %i\n", status); 
       if (status) 
       { 
        if (errno == EISCONN) 
        { 
         status = 0; 
         printf("error = EISCONN so we're good.\n"); 
        } 
       } 
      } 
      // else still waiting... 
     } 
    } 
    else printf("host addr error.\n"); 
} 
else printf("gethostbyname failed.\n"); 

私はこの出力を取得しますEISCONN。だから接続はシーンの裏で働いていますが、セレクトは決してそれを拾いません。選択戻り値の私の理解から、それはfd_set構造体のソケット数を含み、それらのどれもがイベントを持たない場合は0を返します。

私のコードで何が問題になっていますか? PS LgiCurrentTime()は、何らかのポイント(例えば、ポイント)が経過してからミリ秒を返します。 GetTickCount for windows ...私はMac上での正確な実装を忘れていますが、それは重要ではありません。ちょうどタイミング情報です。

答えて

1

私はselect(..)への最初のパラメータはそれ、これまで

int ret = select(s+1, 0, &wr, 0, &t); 
+0

はぁ... OK、その後...最速の答え作る最高のファイル記述子の数+1としませ0あるべきと信じて!私は窓からの難民であり、そのプラットフォームでは最初のパラメータは完全に無視されます。迅速な返信のためのThx。 – fret

+0

Ha;)質問に「meme」も見るのは楽しいことでした。私の会社はMementionという名前です - http://memention.com – epatel

関連する問題