如何实现 epoll 超时?

3
我正在使用epoll进行网络编程,看起来效果不错。我想添加一个超时函数,如果客户端长时间没有发送任何内容,那么它将断开与客户端的连接。
我该如何做?我知道可以在epoll_wait中设置超时时间,但这不是针对单个套接字的...
提前感谢您的帮助。
3个回答

10

按照剩余时间(如果所有套接字的超时时间相同,则等价于按最后收到消息的时间进行排序),保持套接字列表排序。每次调用epoll_wait(),选择剩余时间最短的套接字直到它超时(在列表的前面)。使用该时间作为epoll_wait()中的超时时间。

epoll_wait()返回时,在处理任何活动套接字后,浏览已排序的套接字列表并修剪所有过期的套接字(这些套接字将位于排序列表的开头)。


epoll_wait()时:

timeout = expirylist->expire_time - current_time();
n_events = epoll_wait(epfd, events, maxevents, timeout);

handle_events(events, n_events);

for (client = expirylist; client != NULL && client->expire_time < current_time(); client = client->expire_next)
{
    do_timeout(client);
}

谢谢您的回答。您能否给我展示一下这个的框架代码?很难跟上您的讲解。提前感谢您。 - codereviewanskquestions
1
@LCYSoft:基本思路就是利用第一个客户端到期的时间作为epoll_wait()中的超时时间。请参见更新。 - caf

2
您可以创建一个可重复的 timerfd 并将其添加到 epoll 集合中。它将在您想要的任何时间唤醒您,此时您可以检查所有客户端连接并删除您认为已过期的连接。
如果您的 Linux 版本过旧无法支持 timerfd,则可以尝试使用较旧的 timer_create

我不太确定你所说的“将其添加到 epoll 集”是什么意思。我认为每个客户端的超时时间都不同,因为它们上次连接的时间不同。所以,如果我向 epoll 集中添加一个 timerfd,则所有客户端的超时时间不都相同吗? - codereviewanskquestions
完全没有必要使用timerfd(),因为你可以只需为超时参数指定一个合适的值。 - MarkR

-1

只需使用libevent*或类似的库,这将节省实现自己的队列和检查超时的工作。它还可以使您对epoll的使用更加容易,并且作为额外的好处,更具可移植性(比如说您想在没有epoll但有类似概念的kqueue的FreeBSD上运行应用程序)。

* 还有其他类似的库可供选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接