4

複数のクライアント接続を受け入れて処理できる Web サーバーを構築しています。これに使っselect()ています。
これが行われている間、特定の接続されたソケットにアクティビティ (send または recv) がない場合は、それを閉じたいと思います。したがって、接続されたクライアントから一定期間リクエストが来ない場合は、ソケットを閉じます。そのような接続されたソケットが複数あり、それぞれに対してこの監視を行う必要があります。

Web サーバーは HTTP 1.1 をサポートする必要があるため、永続的な接続を作成するにはこの機能が必要です。

これを行う最善の方法は何ですか?

4

2 に答える 2

1

select呼び出しのタイムアウトを、次のソケットがタイムアウトするまでの最小時間に設定することをお勧めします。次に、タイムアウトになった場合は、アイドル状態のソケットを閉じて、繰り返します。この疑似コードのようなもの:

timeout = default_timeout;
foreach(socket s)
{
    timeout = min(timeout, (s.last_send_or_recv_time + IDLE_TIMEOUT - now()));
}

result = select(..., timeout);
if(result == 0)
{
    foreach(socket s)
    {
        if(now() - s.last_send_or_recv_time >= IDLE_TIMEOUT)
        {
            close(s);
            remove_from_socket_list(s);
        }
    }
}
else
{
    // Handle received data, update last_send_or_recv_time, etc.
}
于 2012-09-05T20:05:05.837 に答える
1

スレッドとブロッキング モードを使用している場合は、ソケットに適切な SO_RCVTIMEOUT を設定するread()だけで済みerrno == EAGAIN/EWOULDBLOCKます。

使用している場合は、select()より複雑です。Adam Rosenfield の提案は表面的にはもっともらしいように見えますが、実際には、他のソケットが十分にビジーである場合、select()タイムアウトはまったく発生しないか、少なくともソケットが実際に死んでから何分間も発生しない可能性があります。サーバーで行う必要があるように、タイムアウトを厳密に適用する場合は、最終読み取り時刻を各ソケットに関連付ける必要があり、select()ループの最後で、準備ができていないfdfd を選択してセットを反復処理する必要があります。それらの最終読み取り時間を確認し、あまりにも死んでいるものを閉じます。

于 2012-09-06T02:08:04.673 に答える