2011-10-03 8 views
19

私は自分のソケット間の通信にselect関数を使用しています。私はwhileループを持っています。 -なぜループ内のselect()のFD_SET/FD_ZEROですか?

while(!done) { 

    FD_ZERO(&read_flags); 
    FD_ZERO(&write_flags); 
    FD_SET(comm_fd1, &read_flags); 
    FD_SET(comm_fd2, &read_flags); 
    FD_SET(STDIN_FILENO, &read_flags); 
    FD_SET(comm_fd1, &write_flags); 
    FD_SET(comm_fd2, &write_flags); 
    FD_SET(STDIN_FILENO, &write_flags); 

    //call select 
    sel = select(comm_fd1+comm_fd2+1, &read_flags, &write_flags, (fd_set*)0, &waitd); 

クライアント側でも同じ変数が使われています。私はチュートリアルのオンラインからこの基本的なテクニックを得て、ちょうどそれと一緒に行きました。それから、私は、なぜ私はループを作るたびに、ファイルディスクリプタをクリアしてファイルディスクリプタを追加するのですか?それらが既に追加されている場合、なぜそれらをクリアして、もう一度追加しますか?だから私はしばらく前に一度だけこれをやってみましたが、コードはもう同じように動作しません。なぜ誰かが説明できますか? selectはセットの内容を変更するだけなのか?どんな助けや洞察もありがとうございます。

答えて

21

selectが返ってくると、どのファイル記述子が読み込み/書き込み/例外の準備ができているかを示すようにセットが更新されました。その他のフラグはすべてクリアされています。

別の選択を開始する前にクリアされたファイルディスクリプタを再び有効にすることが重要です。そうしないと、ファイルディスクリプタで待機しなくなります。

ファイルディスクリプタのセットを変更する必要がある場合(新規に開かれたソケットを読み取りセットに追加するなど)、再クリアすることができます。それをクリアし、毎回それを再構築するので、プログラムの状態が変わると正しいことになります。

+2

ループするたびにtimeval構造体(例ではwaitd)をリセットする必要があることにも注意してください。 –

3

選択がセットの内容を変更するだけであるのか?

はい、selectが返された後、準備完了ディスクリプタのみがセット内に残ります。

関連する問題