1
fd_set rset;
struct timeval tv;
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
tv.tv_sec = 1;
tv.tv_usec = 0;

for(;;)
{
  for(count = 0; count < elements in sockaddr_in array; count++)
  {
    //flag_array is filled with -1 before for(;;)
    if(flag_array[count] == -1 && select(sockfd+1, &rset, NULL, NULL, &tv))
    {
      recvfrom(...)
    }
    tv.tv_sec = 1;
    FD_ZERO(&rset);//this fixed it
    FD_SET(sockfd, &rset);//and this too
  }

  //contact everyone from sockaddr array (works like a charm!)
}

「タイムアウト」が発生する前に他のプログラムからこのプログラムにメッセージを送信しないと、select ステートメントが「失敗」するため、その中で recvfrom ステートメントを使用できません。私はかつて、他のプログラムが無限ループでこれに連絡するようにしましたが、if ステートメントの中に入ることはありませんでした。

何が機能するか: 各タイムアウトが発生する前にこのプログラムに連絡すれば、すべて問題ありません。recvfrom ステートメントを if(___ && select) の外に置くと、完全に正常に動作します。

以下は、このプログラムが Recv と呼ばれる小さな図です。

if(A contacts Recv before timeout)    count = 0
   Recv stores contact A in struct
if(B contacts Recv before timeout)    count = 1
   Recv stores contact B in struct
if(timeout)                           count = 2

if(C contacts Recv after timeout)     count = 3
   nothing
                                      count = 4

プログラムは A と B に正常に接続します //ループの開始に戻ります

flag_array == -1 is false             count = 0
flag_array == -1 is false             count = 1
flag_array == -1 is true...select "fails" count = 2..3..4..(exit loop)

これを投稿する 2 分前に、以前のコードを最後にもう一度確認することにしました。忘れたらしい

FD_ZERO(&rset);
FD_SET(sockfd, &rset);

for ループ (tv.tv_sec = 1) の後。

なぜこれを行う必要があるのか​​ 誰かが詳しく説明できますか?

4

2 に答える 2

4

select() 渡されたを変更fd_setします - を呼び出すたびに設定する必要がありますselect()。これがまさにどのように機能するかselect()です。

于 2011-04-17T23:55:47.230 に答える
3

select()ファイル記述子セットを変更する可能性があるため、必要です。

select(3) の Linux マンページからの引用:

正常に完了すると、pselect() または select() 関数は、readfds、writefds、および errorfds 引数によって指されるオブジェクトを変更して、どのファイル記述子が読み取りの準備ができているか、書き込みの準備ができているか、または保留中のエラー状態を持っているかをそれぞれ示します。 、およびすべての出力セット内の準備ができている記述子の総数を返すものとします。nfds 未満の各ファイル記述子について、入力時に設定され、関連する条件がそのファイル記述子に対して真である場合、対応するビットは正常終了時に設定されます。

select()その引数も変更される可能性があることに注意してくださいstruct timeval。たとえば、Linux は経過時間を格納します。したがって、すべてのフィールドもリセットする必要がありtvます。

于 2011-04-17T23:58:39.913 に答える