2011-11-12 8 views
1

私は、私が取り組んでいる単純なサーバー/クライアントプログラムを持っています。私はselect()を使用して、データを読み込む前にTCPソケットにデータが入るのを待ちます。データが入ってくるまで、私はすべてそれを得るまで、複数のrecv()select()コールをチャンクで読み込みます。次に、最初のselect()コールにループバックし、クライアントに何か他のものがあるかどうかを確認します。2回目のソケットセレクト()ブロック

struct timeval timeoutCounter; 
fd_set readFileDescriptor; 
do { 
    timeoutCounter.tv_sec = 30; 
    timeoutCounter.tv_usec = 0; 
    FD_ZERO(&readFileDescriptor); 
    FD_SET(socket, &readFileDescriptor); 
    cout << "This line always prints, every iteration through the loop.\n"; 
    dataReady = select(socket+1,&readFileDescriptor,NULL,NULL,&timeoutCounter); 
    cout << "This line only prints the first time I call select()." 
     << "The second time it hangs before reaching this line.\n"; 

    // ... recv(), select(), recv(), select(), etc in a loop until I have all the data 
    // send() a response to the client 
} while(dataReady > 0); 

これは大変読みにくい関数で始まりました。それから、私はそれを別のクラスに分割しました。それはaccept()です。そして、その動作は異なっています。ユーザーが送信する最初のデータセットは正常に受信されます。しかし、クライアントはサーバーからの応答を待ってから、ソケットに第2のデータセットを送信します。ただし、クライアントが2番目のデータセットを送信した後にはselect()が返されません。タイムアウトするまでブロックします。

私はすでに問題があるとクライアントを排除しました。パケットは適切なタイミングで正常に送信されます。また、ソケットファイル記述子を印刷して、どこかで変更されていないことを証明しようとしました。なぜ誰かがこのコードがうまくいかない理由を知っていますか? select()をブロックする要因は何ですか?

編集:私のコードは32ビットマシンで正常に動作しますが、64ビットマシンでは動作しません。私はまだ問題を解決していないが、それは良いビットを狭める。

+1

誰かのようなサウンドは、 'socket'変数を壊しています。 strace(1)を使ってサーバを実行して、selectとrecvのすべての引数が期待どおりであることを確認してください。または、デバッガのサーバーをシングルステップで呼び出し、システムコールの引数を確認します –

答えて

3

あなたの完全なコードを見ることなく、何が間違っているのかを知るのは難しいです。ただし、select()ファンクションは、の値をfd_setに変更します。 select()を呼び出す前に、それぞれのfd_set値を再初期化して、必要なソケットを含める必要があります。

はあなたが本当にあなたもselect()を呼び出す必要がない場合もタイムアウト機能を必要としない限り、それは一部データを取得するまでrecv()関数はブロックします(またはソケットが閉じている)ということも忘れないでください。最後に、のいずれかのデータが利用可能であれば、recv()関数が返されます。必ずしもすべてあなたが求めたもののすべてのデータを取得するには、ループ内でrecv()を繰り返し呼び出す必要があります。 これは、少数のバイトを読み込んでいても当てはまります。

+0

ええ、私は知っています。コードそのものは非常に長く、何百行もの話をしています。そのほとんどはエラーチェックです。人々が本当にそれを歩きたいなら、私はそれを掲示することができます。 私はfd_set値をリセットしますが、私が選択する前は常にFD_ZEROとFD_SETを呼び出します –

関連する問題