epoll and timeouts
Asked Answered
C

2

5

I'm using epoll to manage about 20 to 30 sockets. I figure out that epoll_wait can be used to wait for some data to arrive over one of the socket but I'm missing how do I implement timeouts on socket level. I can use timeout on epoll_wait but it not very useful in my case. For example, if I need to every close a socket where no activity is recorded for > 500 ms orr may be send some data to a socket every 200 ms no matter what. How can these socket level timeout be implemented using epoll? Any suggestion and idea would be appreciated!

Thanks, Shivam Kalra

Communalize answered 27/5, 2012 at 6:56 Comment(0)
K
6

Sounds like you're trying to write an event loop (if so have a look at libev btw). epoll will not help you there, you have to keep track of socket inactivity yourself (clock_gettime() or gettimeofday() for instance), then wake up several times a second and check everything you need.

Some pseudo code

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

This will wake you up 200 times a second if all sockets are inactive.

The inactivity check requires a list of the sockets to be examined along with timestamps of the last inactivity:

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 */
        ...
    }
}

where diff() gives you the difference of 2 struct timevals and now() gives you the current timestamp.

Kagoshima answered 27/5, 2012 at 7:8 Comment(2)
Thanks for the reply. But, I was wondering, if I could use inactivity check with epoll wait for very small time may be about 10 ms? Do I get any performance improvement over select + inactivity chec?Communalize
Depends, the more often you wake up the more CPU you will consume. Also, you need a 1000 HZ kernel to wake up every millisecond. Like I said, I highly suggest a ready event-loop (like libev, or libevent) which are optimised to these situations (at the price of a dependency).Kagoshima
R
12

Try pairing each socket with a timer fd object (timerfd_create). For each socket in your application, create a timer that's initially set to expire after 500ms, and add the timer to the epoll object (same as with a socket—via epoll_ctl and EPOLL_CTL_ADD). Then, whenever data arrives on a socket, reset that socket's associated timer back to a 500ms timeout.

If a timer expires (because a socket has been inactive for 500ms) then the timer will become "read ready" in the epoll object and cause any thread waiting on epoll_wait to wake up. That thread may then handle the timeout for the timer's associated socket.

Repentance answered 26/8, 2013 at 23:47 Comment(0)
K
6

Sounds like you're trying to write an event loop (if so have a look at libev btw). epoll will not help you there, you have to keep track of socket inactivity yourself (clock_gettime() or gettimeofday() for instance), then wake up several times a second and check everything you need.

Some pseudo code

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

This will wake you up 200 times a second if all sockets are inactive.

The inactivity check requires a list of the sockets to be examined along with timestamps of the last inactivity:

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 */
        ...
    }
}

where diff() gives you the difference of 2 struct timevals and now() gives you the current timestamp.

Kagoshima answered 27/5, 2012 at 7:8 Comment(2)
Thanks for the reply. But, I was wondering, if I could use inactivity check with epoll wait for very small time may be about 10 ms? Do I get any performance improvement over select + inactivity chec?Communalize
Depends, the more often you wake up the more CPU you will consume. Also, you need a 1000 HZ kernel to wake up every millisecond. Like I said, I highly suggest a ready event-loop (like libev, or libevent) which are optimised to these situations (at the price of a dependency).Kagoshima

© 2022 - 2024 — McMap. All rights reserved.