3

epoll を使用して、約 20 から 30 のソケットを管理しています。epoll_wait を使用して、一部のデータがソケットの 1 つを介して到着するのを待機できることがわかりましたが、ソケット レベルでタイムアウトを実装する方法がわかりません。epoll_wait でタイムアウトを使用できますが、私の場合はあまり役に立ちません。たとえば、500 ミリ秒を超えるアクティビティが記録されていないソケットを毎回閉じる必要がある場合、または何があっても 200 ミリ秒ごとにソケットにデータを送信することができます。これらのソケット レベルのタイムアウトは、epoll を使用してどのように実装できますか? 任意の提案やアイデアをいただければ幸いです!

ありがとう、シヴァム・カルラ

4

2 に答える 2

7

各ソケットをタイマー fd オブジェクトとペアにしてみてください ( timerfd_create)。アプリケーションのソケットごとに、最初は 500 ミリ秒後に期限切れになるように設定されたタイマーを作成し、そのタイマーを epoll オブジェクトに追加します(ソケットの場合と同じ —epoll_ctlと を使用EPOLL_CTL_ADD)。次に、データがソケットに到着するたびに、そのソケットに関連付けられているタイマーを 500 ミリ秒のタイムアウトにリセットします。

タイマーが期限切れになると (ソケットが 500 ミリ秒非アクティブになったため)、タイマーは epoll オブジェクトで「読み取り可能」になり、待機中のスレッドがepoll_wait起動します。そのスレッドは、タイマーに関連付けられたソケットのタイムアウトを処理できます。

于 2013-08-26T23:47:58.963 に答える
6

イベントループを作成しようとしているようです(もしそうなら、libev btwを見てください)。 そこでは役に立ちません。自分で(またはたとえば)epollソケットの非アクティブ状態を追跡してから、1秒間に数回ウェイクアップして、必要なものをすべてチェックする必要があります。clock_gettime()gettimeofday()

いくつかの擬似コード

while (1) {
    n = epoll_wait(..., 5);
    if (n > 0) {
        /* process activity */
    } else {
        /* process inactivity */
    }
}

これにより、すべてのソケットが非アクティブの場合、1秒間に200回ウェイクアップします。

非アクティブチェックでは、最後に非アクティブだったタイムスタンプとともに、調査するソケットのリストが必要です。

struct sockstamp_s {
    /* socket descriptor */
    int sockfd;
    /* last active */
    struct timeval tv;
};

/* check which socket has been inactive */
for (struct sockstamp_s *i = socklist; ...; i = next(i)) {
    if (diff(s->tv, now()) > 500) {
        /* socket s->sockfd was inactive for more than 500 ms */
        ...
    }
}

ここで、2秒のdiff()差が得られ、現在のタイムスタンプが得られます。struct timevalnow()

于 2012-05-27T07:08:47.643 に答える