5

このアプリケーションは、接続および選択操作(cコード)でノンブロッキングソケットを使用します。pusedoコードは次のとおりです。

unsigned int ConnectToServer(struct sockaddr_in *pSelfAddr,struct sockaddr_in *pDestAddr)
    {
         int sktConnect = -1;
         sktConnect = socket(AF_INET,SOCK_STREAM,0);
         if(sktConnect == INVALID_SOCKET)
             return -1;
         fcntl(sktConnect,F_SETFL,fcntl(sktConnect,F_GETFL) | O_NONBLOCK);
         if(pSelfAddr != 0)
         {
             if(bind(sktConnect,(const struct sockaddr*)(void *)pSelfAddr,sizeof(*pSelfAddr)) != 0)
             {
                 closesocket(sktConnect);
                 return -1;
             }
         }
         errno = 0;
         int nRc = connect(sktConnect,(const struct sockaddr*)(void *)pDestAddr, sizeof(*pDestAddr));
         if(nrC != -1)
         {
             return sktConnect;
         }
         if(errno != EINPROGRESS)
         {
             int savedError = errno;
             closesocket(sktConnect);
             return -1;
         }
         fd_set scanSet;
         FD_ZERO(&scanSet);
         FD_SET(sktConnect,&scanSet);
         struct timeval waitTime;
         waitTime.tv_sec = 2;
         waitTime.tv_usec = 0;
         int tmp;
         tmp = select(sktConnect +1, (fd_set*)0, &scanSet, (fd_set*)0,&waitTime);
         if(tmp == -1 || !FD_ISSET(sktConnect,&scanSet))
         {
             int savedErrorNo = errno;
             writeLog("Connect %s failed after select, cause %d, error %s",inet_ntoa(pDestAddr->sin_addr),savedErrorNo,strerror(savedErrorNo));
             closesocket(sktConnect);
             return -1;
         } 
    .        .        .     .     .}

そのようなノードは80あり、アプリケーションはラウンドロビン方式ですべてのピアに接続します。このフェーズでは、一部のノードがエラー番号115で接続できません(api –接続+選択)。

以下の成功シナリオの(tcpdump出力の)ログでは、(SYN、SYN + ACK、ACK)を確認できますが、tcpdumpログに障害が発生したノードのSYNのエントリはありません。

tcpdumpログは次のとおりです。

387937 2012-07-05 07:45:30.646514 10.18.92.173          10.137.165.136        TCP      33728 > 8441 [SYN] Seq=0 Ack=0 Win=5792 Len=0 MSS=1460 TSV=1414450402 TSER=912308224 WS=8 
387947 2012-07-05 07:45:30.780762 10.137.165.136        10.18.92.173          TCP      8441 > 33728 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=912309754 TSER=1414450402 WS=8 
387948 2012-07-05 07:45:30.780773 10.18.92.173          10.137.165.136        TCP      33728 > 8441 [ACK] Seq=1 Ack=1 Win=5888 Len=0 TSV=1414450435 TSER=912309754 
All the above three events indicate the success information.
387949 2012-07-05 07:45:30.782652 10.18.92.173          10.137.165.136        TCP      33728 > 8441 [PSH, ACK] Seq=1 Ack=1 Win=5888 Len=320 TSV=1414450436 TSER=912309754 
387967 2012-07-05 07:45:30.915615 10.137.165.136        10.18.92.173          TCP      8441 > 33728 [ACK] Seq=1 Ack=321 Win=6912 Len=0 TSV=912309788 TSER=1414450436 
388011 2012-07-05 07:45:31.362712 10.18.92.173          10.137.165.136        TCP      33728 > 8441 [PSH, ACK] Seq=321 Ack=1 Win=5888 Len=320 TSV=1414450581 TSER=912309788 
388055 2012-07-05 07:45:31.495558 10.137.165.136        10.18.92.173          TCP      8441 > 33728 [ACK] Seq=1 Ack=641 Win=7936 Len=0 TSV=912309933 TSER=1414450581 
388080 2012-07-05 07:45:31.702336 10.137.165.136        10.18.92.173          TCP      8441 > 33728 [PSH, ACK] Seq=1 Ack=641 Win=7936 Len=712 TSV=912309985 TSER=1414450581 
388081 2012-07-05 07:45:31.702350 10.18.92.173          10.137.165.136        TCP      33728 > 8441 [ACK] Seq=641 Ack=713 Win=7424 Len=0 TSV=1414450666 TSER=912309985 
388142 2012-07-05 07:45:32.185612 10.137.165.136        10.18.92.173          TCP      8441 > 33728 [PSH, ACK] Seq=713 Ack=641 Win=7936 Len=320 TSV=912310106 TSER=1414450666 
388143 2012-07-05 07:45:32.185629 10.18.92.173          10.137.165.136        TCP      33728 > 8441 [ACK] Seq=641 Ack=1033 Win=8704 Len=0 TSV=1414450786 TSER=912310106 
388169 2012-07-05 07:45:32.362622 10.18.92.173          10.137.165.136        TCP      33728 > 8441 [PSH, ACK] Seq=641 Ack=1033 Win=8704 Len=320 TSV=1414450831 TSER=912310106 
388212 2012-07-05 07:45:32.494833 10.137.165.136        10.18.92.173          TCP      8441 > 33728 [ACK] Seq=1033 Ack=961 Win=9216 Len=0 TSV=912310183 TSER=1414450831 
388219 2012-07-05 07:45:32.501613 10.137.165.136        10.18.92.173          TCP      8441 > 33728 [PSH, ACK] Seq=1033 Ack=961 Win=9216 Len=356 TSV=912310185 TSER=1414450831 
388220 2012-07-05 07:45:32.501624 10.18.92.173          10.137.165.136        TCP      33728 > 8441 [ACK] Seq=961 Ack=1389 Win=10240 Len=0 TSV=1414450865 TSER=912310185 

接続時にエラーを通知するアプリケーションログ(つまり、api-接続+選択)

[5258: 2012-07-05 07:45:30]Connect [10.137.165.136 <- 10.18.92.173] success. 
[5258: 2012-07-05 07:45:32]Connect 10.137.165.137 fail after select, cause:115, error Operation now in progress. Check whether remote machine exist and the network is normal or not. 
[5258: 2012-07-05 07:45:32]Connect to server([10.137.165.137 <- 10.18.92.173], port=8441) Failed!

tcpdumpの最初の3つのエントリに対応する成功ログ。そして、tcpdumpにイベントがない障害ログ

私の質問は次のとおりです。クライアントが失敗した場合に「接続」APIを開始すると、クライアント側のtcpdumpでイベントを確認できません(最初のSYNでも)。このランダム性の理由は何でしょうか。

4

2 に答える 2

2

ヒットしEINPROGRESSました。connectマニュアルページから:

ソケットはブロックされておらず、接続をすぐに完了することはできません。書き込み用のソケットを選択することにより、完了のために(2)またはpoll(2)を選択することができます。select(2)が書き込み可能性を示したら、getsockopt(2)を使用してレベルSOL_SOCKETのSO_ERRORオプションを読み取り、connect()が正常に完了したか(SO_ERRORがゼロ)または失敗したか(SO_ERRORはここにリストされている通常のエラーコードの1つであり、失敗の理由)。

これはEINPROGRESS、使用可能なローカルポートとルーティングキャッシュエントリがあるにもかかわらず、カーネルが現在接続を完了できないことを示しています。これは、ソケットの状態がまだ「ESTABLISHED」に移行していない場合に発生するようです。もう一度ソケットを待つだけですが、後でselect電話して、完了したかどうかを確認してください。getsockoptconnect

理由については、接続中にソケットがSYN_SENT状態に移行しますが、パケットはまだ出力キューにある可能性があり、実際にはまだネットワークデバイスバッファに到達していません。

于 2012-07-05T16:12:37.547 に答える
0

戻った後select()、実際にはソケットの現在のステータスを取得していません。(呼び出しerrnoから残った)に古い値が表示されています。connect()ほとんどの場合select()、タイムアウト後に単に戻ってきます。

getsockopt(sktConnect, SOL_SOCKET, SO_ERROR, &err, ...)戻った後、ソケットの実際のステータスを取得するには、を呼び出す必要がありselect()ます。

于 2012-07-06T13:22:21.607 に答える