我正在使用 epoll 来管理大约 20 到 30 个套接字。我发现 epoll_wait 可用于等待一些数据通过其中一个套接字到达,但我错过了如何在套接字级别实现超时。我可以在 epoll_wait 上使用超时,但在我的情况下它不是很有用。例如,如果我需要每次关闭一个超过 500 毫秒没有记录活动的套接字,或者无论如何都可能每 200 毫秒向一个套接字发送一些数据。如何使用 epoll 实现这些套接字级别的超时?任何建议和想法将不胜感激!
谢谢, 希瓦姆卡拉
尝试将每个套接字与计时器 fd 对象 ( timerfd_create
) 配对。对于应用程序中的每个套接字,创建一个最初设置为在 500 毫秒后过期的计时器,并将计时器添加到 epoll 对象(与套接字相同——通过epoll_ctl
和EPOLL_CTL_ADD
)。然后,每当数据到达套接字时,将该套接字的关联计时器重置为 500 毫秒超时。
如果一个定时器到期(因为一个套接字已经 500 毫秒处于非活动状态),那么定时器将在 epoll 对象中变为“读就绪”,并导致任何等待epoll_wait
唤醒的线程。然后,该线程可以处理定时器相关套接字的超时。
听起来您正在尝试编写事件循环(如果是这样,请查看libev btw)。 在那里不会帮助你,你必须自己(或例如)epoll
跟踪套接字不活动,然后每秒唤醒几次并检查你需要的一切。clock_gettime()
gettimeofday()
一些伪代码
while (1) {
n = epoll_wait(..., 5);
if (n > 0) {
/* process activity */
} else {
/* process inactivity */
}
}
如果所有套接字都处于非活动状态,这将每秒唤醒您 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 */
...
}
}
wherediff()
为您提供 2struct timeval
秒的差异并now()
为您提供当前时间戳。