私はソケットプログラミングが初めてで、それがどのように機能するかを完全に理解しようとしていますが、今のところ私はselect()
.
問題は、私のコードでは、select がアクティビティを検出し、fd が設定されたままにFD_ISSET
なると、select 関数を無視するように、次の反復で自動的に true が返されるように見えることです。問題はこれと同じようですが、そこで見つけたすべてのことを行いましたが、役に立たなかった: http://compgroups.net/comp.unix.programmer/how-does-fd_isset-return-0-after-returne /55058
私はLinuxを使用しているため、後でtimeval変数を再初期化するようにしました。select()
この関数はOSごとに異なる動作をすることを理解していたため、selectの前FD_ZERO
と前にfdセットも再初期化しました。FD_SET
私は何を間違っていますか?コードは次のとおりです。
#include <stdio.h>
#include <strings.h>
#include <sys/select.h>
#include <sys/time.h>
int main () {
struct timeval tv;
tv.tv_sec = 5; // 5 seconds timeout
tv.tv_usec = 0;
fd_set afds, rfds;
FD_ZERO(&afds);
FD_SET(0, &afds);
while (1) {
rfds = afds;
select(1, &rfds, NULL, NULL, &tv);
// linux, reinitialize tv?
tv.tv_sec = 5;
tv.tv_usec = 0;
// so at this point after select runs the first time and detects STDIN activity
// it will enter an infinite loop printing "fd 0 is set" (why?)
if (FD_ISSET(0, &rfds)) {
printf("fd 0 is set\n");
FD_CLR(0, &rfds);
} else {
printf("fd 0 is NOT set\n");
}
}
}
私は新しいユーザーであり、これに答えることができないため、質問を編集します。
実際のところ、afds の値が割り当てられるときは select の前に rfds を初期化します。この値は常に FD_ZERO(&afds); で設定されます。FD_SET(0, &afds); これはまだ私にはうまくいきません。
これが私が理解していることです:
afds に stdin ファイル記述子を追加します
while 無限ループ、rfds = afds に入ります (rfds はループの開始時に常に = afds になります)。
また、このとき、FD_ISSET(0, &rfds) は常に != 0 になります。
select には 5 秒のタイムアウトがあるため、この時点で 5 秒が経過する前に何も入力しないと終了します。UNSETTING FD_ISSET(0, &rfds) - 正しいですか? そのため、何も入力されていない場合、select は実際に fd 0 の設定を解除します。これはうまくいくようです
タイムアウトの前に何かを入力すると、問題が発生します。この時点で、FD_ISSET(0, &rfds) は != 0 を返し、fd 0 が設定されていることを出力し、各ループ fd が設定されます。
わかりました、これは正確ですか、私はそれを正しく理解しましたか? fd の準備ができて終了することを実際に検出し、fd != 0 を設定するため、実際には select は時間が経過するのを待ちません。
さらなる質問が必要です:サーバーが時々複数のクライアントに自動的にメッセージを送信する必要がある場合(クライアントから読み取ったものとは関係なく)、コードを適応させることで select と gettimeofday でそれを行うことは可能でしょうか?その上?
助けてくれてありがとう。