• ベストアンサー

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)について

見当違いな質問かもしれませんがお願いします。 複数のソケットを監視する際にselectを使う場合のことですが、 selectの動作と戻り値について疑問があります。 http://www.linux.or.jp/JM/html/LDP_man-pages/man2/select.2.html ここを参照すると、selectの戻り値は 「更新された 3 つのディスクリプタ集合に含まれているディスクリプタの数 (つまり、 readfds, writefds, exceptfds 中の 1 になっているビットの総数) を返す。」 とあります。 私の中でselectは登録してあるFDのうち、一つでも動きがあれば即座にselectを抜けるもの、という認識です。 この認識だとreadfds,writefdsが引数として与えられているとしても、 どちらかのfd_setのうち、一つでも動きがあればselect文は 抜けてしまうことになります。とすると、戻り値として 「readfds, writefds, exceptfds 中の 1 になっているビットの総数」 は常に1ということになってしまいます。しかし、総数というからには 複数同時に1になることもあるはずです。 私の認識が間違っているとは思うのですが、どう間違っているのかわかりません。 select文の動きについて詳しく教えていただけないでしょうか。 または良いページがあれば教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.1

>私の中でselectは登録してあるFDのうち、一つでも動きがあれば即座にselectを抜けるもの、という認識です。 この認識はあっています。 しかし、selectを呼び出す以前にOKになっているFDがあれば、それらは全てビットがONになります。 話しを簡単にする為に、受信のみのソケットを3つ作成したとします。 これらの3つのソケットに向けて相手が電文を送ったとします。 その状態でまだ、こちらはselectを呼び出さずにいます。しばらくしてから、selectを呼び出すと、selectは即座にリターンし、3つのビットが一度にONになっているはずです。 一方、相手が、一切電文を送ってない状態で、selectを呼び出した場合は、何れかのビットがONになればリターンするので、そのときは、貴方が想像しているように ビットの総数は1になる可能性が高いです。 従って、相手が電文を送る前にselectを呼び出すか、送った後にselectを呼び出すかは、その時のタイミングにより異なります。従って、ビット数の総和が常に1であるとは、考えない方が無難です。(1つのソケットしか使用しない場合は別ですが・・・)

ponshige
質問者

お礼

いつもありがとうございます。 >selectを呼び出す以前にOKになっているFD あ。。言われてみればその通りでした。 適切なご回答大変助かりました。

その他の回答 (1)

  • uu0v0uu
  • ベストアンサー率31% (17/54)
回答No.2

#1 さんの回答で合っていると思います。 例えば、selectをループの中に入れて使用するとして、ループして何か処理してる間に複数のFDが使用可能になっている可能性は十分にあります。 ↓こんなイメージ for(;;){   select();   if(sock1->recv()>0){  }   if(sock2->recv()>0){  }   if(sock3->recv()>0){  } } 余談ですが、 ご使用になるのがwinsockだと微妙に使用法が違います。 返るのはビット列ではなくて、ディスクリプタの配列になるようです。(結局FD_ISSETで検知するので違いは吸収されますが) また、引数のnにはディスクリプタの最大値+1(以上)を指定しないと期待通り動作しないはずですが、winsockではこの値は見てませんのでなんでも良いです。 さらに、readfds、writefds、exceptfdsを全てNULLにしてタイマーとして動作させようとすると、確かコンパイルエラーになったと思います。 私が使用したのはBorlandなので、VCだとまた事情が異なるかもしれません。

ponshige
質問者

お礼

ありがとうございます。 そうですね。他に処理している間にも 複数のクライアントからデータが送られてくることが ありますね。完全に考えから抜け落ちてました。 使用するのはUnixですが、winsockのお話も 参考になりました。winsockではタイマーにならないんですか。。 昨日タイマーになるということを知ったばかりだったのでタイムリーでした(笑) Borland環境はないですが、知識として蓄積させていただきます。

関連するQ&A