1

現在、 winsock を使用してサーバーを構築しています。私のサーバーは複数のクライアントを扱うので、select() 関数と読み取り、書き込み、および例外セットを使用しています。特定のソケットがタイムアウトした場合、 select() が 0 を返すことは既に知っています。

しかし、タイムアウトになった実際のソケットを特定するにはどうすればよいでしょうか?

ところで、FD_ISSET(Some_Socket, &Exception) が true を返すために Some_Socket に何が起こる必要があるか教えてもらえますか?

上記の関数を使用して、セット内のすべてのソケットをチェックできますか?

編集:

この例があるとしましょう:

int main(void){

       fd_set rfds;
       struct timeval tv;
       int retval;

       /* Watch stdin (fd 0) to see when it has input. */
       FD_ZERO(&rfds);

       for(int i = 0; i<clientcount; i++) {


        FD_SET(sockets[i].Scksas, &read_mask);

        FD_SET(sockets[i].Scksas, &write_mask);

        FD_SET(sockets[i].Scksas, &excep_mask);

   }

       /* Wait up to five seconds. */
       tv.tv_sec = 5;
       tv.tv_usec = 0;

       retval = select(1, &rfds, NULL, NULL, &tv);
       /* Don't rely on the value of tv now! */

       if (retval == -1)
           perror("select()");
       else if (retval)
           printf("Data is available now.\n");
           /* FD_ISSET(0, &rfds) will be true. */
       else{

           printf("No data within five seconds.\n");

           /*
             Handle timed out socket, but which one ?
           */
       }
       exit(EXIT_SUCCESS);
   }

タイムアウトになったソケットを特定するにはどうすればよいですか?

4

3 に答える 3

2

select問題は、タイムアウトが単一のソケットではなくセット全体に対するものであるため、et al. を使用できないことです。

一定期間通信していない個々のソケットを見つけるには、3 つの簡単な解決策があります。

  1. 最も簡単なのは、おそらくソケットごとに構造を保持することであり、この構造には最後の通信の時刻があります。一定の間隔で、すべてのソケットのこの時間をチェックし、時間が長すぎる場合は接続を閉じます。

  2. もう 1 つの解決策は、プロトコルに「キープ アライブ」メッセージを含めることです。一定の間隔で、すべてのソケットで「are you alive」メッセージを送信します。一定のタイムアウト内に「私は生きています」という応答が得られない場合は、接続が古くなったと見なされる可能性があるため、接続を閉じることができます。

  3. ソケットごとに個別のスレッドまたはプロセスを使用します。selectセットにはソケットが1つしかないため、使用できます。

于 2013-01-17T12:20:11.600 に答える
1

より具体的にselect()は、指定されたタイムアウトでソケットが選択されていない場合は 0 を返します。戻り値が正の数の場合、それは設定されているソケットの数です (負の戻り値は選択エラーです)。どのソケットがどこに設定されているかを知る適切な方法は、FD_ISSET各ソケット、各セットで使用することです。

if ( 0 != FD_ISSET( sock, &efds ) )...
于 2013-01-17T13:25:06.093 に答える
0

特定のソケットがタイムアウトした場合、select() が 0 を返すことは既に知っています。

いいえ、ありません。すべてのソケットがタイムアウトした場合はゼロを返します。その場合は簡単です。それらをすべて閉じます。

ゼロ以外が返された場合は、読み取り/書き込み FD セット内のすべての FD を処理する必要があります。その後、それらのセットに含まれていなかったすべての FD を処理できます。すべての FD の最後の I/O 時間を維持し、そのループでタイムアウト制限を超えていないかどうかを確認する必要があります。

于 2013-01-17T18:12:16.373 に答える