0

C で、サーバー アプリケーションがあるとします。ソケットは適切にセットアップされ、ローカル ポートにバインドされており、listen() 関数はエラーなしで呼び出されています。

次のようなコード:

    //obtain a connection.
    int connection;
    struct sockaddr_storage sender;
    socklen_t addr_size = sizeof(sender);
    if((connection=accept(sockfd, (struct sockaddr*)&sender, &addr_size))==-1)
            {close(sockfd); return -1; }
    if(close(sockfd)==-1){
            close(connection);
            return -1;
    }
    else
            return connection;

クライアントからデータを読み取ることができる接続ファイル記述子を正常に取得します。

私のアプリケーションでは、サーバーが一定時間待機し、接続が確立されていない場合はオフになって他のことを行う必要があります。さらに、最大 1 つの接続が受け入れられます。Accept() はブロッキング システム コールですが、ブロッキングは避けたいと思います。

これに対処するには、さまざまな方法があるようです。

  • SEの質問では、select を使用してこれを解決することが提案されていますが、select は多くのファイル ハンドルを一度に監視するように設計されており、ここではやり過ぎのようです。

  • 別の質問は、ソケットを非ブロックに変更してから、接続が確立されたかどうかをループでチェックすることを提案しています。これも機能しますが、ブロックしたいので、あまり良くありません-永遠にではありません.

  • 他の言語では、ブロッキングを防ぐために SIGALARM と alarm() コマンドを使用しているように見えますが、私のアプリケーションには複数のスレッドがあり、これはエラーが発生しやすいソリューションのようです。

  • 他のいくつかの言語 (Java?) では、これを実現するために渡すことができるタイムアウト引数があると思います。ここではそれが理想的ですが、C のソケットに同様の関数が見つからないようです。

これに対処するより良い方法はありますか?他の誰かがすでに理解しているようなことのようです。より良い方法がない場合、上記の解決策のうちどれが最も適切ですか? 私はソケットをノンブロッキングにする方向に傾いていますが、それは大量の余分なクラフトを導入しているようです.

4

1 に答える 1

1

select を使用するときは、常に fcntl() でファイル記述子をブロックしないようにすることを忘れないでください。そうしないと、クライアントが接続を開始し、select が戻り、クライアントが終了し、accept() でサーバーが永久にブロックされる可能性があります。

受け入れが成功した後、プログラムがこのように動作する場合は、ファイル記述子を再びブロック モードにすることができます。

于 2012-11-15T19:50:00.170 に答える