在基于epoll的服务器中超时空闲连接 [英] Time out idle connections in epoll based server

查看:546
本文介绍了在基于epoll的服务器中超时空闲连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用c编写一个TCP服务器,该服务器使用epoll()I/O复用来管理并发连接.我想使闲置时间超过允许时间的连接超时.

I'm writing a tcp server in c that uses epoll() i/o multiplexing to manage concurrent connections. I want to timeout connections that have been idle for more than an allowed time.

到目前为止,我保留了与每个连接关联的last_active time_t变量,该变量在事件处理程序中更新为当前时间.在此之前,我检查自上一次事件以来是否已超过允许的时间,如果是,则终止连接.

So far I keep a last_active time_t variable associated with each connection, which I update to the current time in the event handler. Before doing that, I check if more than the allowed time has ellapsed since last event and if so I terminate the connection.

到目前为止还不错,但这并不是我真正想要的,因为超时仅在第一个超时事件中触发,但是如果连接保持不活动状态,我的代码只有在其变为活动"状态时才会检测到它再次.

So far so good but it's not really what I want because the timeout is only triggered on the first out-of-time event, but if the connection remains inactive, my code doesn't detect it until it becomes "active" again.

我在基于select()的服务器上看到的方法是在事件循环的每次迭代期间线性遍历兴趣集并清除那里的非活动连接.在选择中这不是问题,因为无论如何您都已经必须执行此遍历,但是我正使用epoll()来避免执行此操作.如果执行此操作,则epoll并不比select更好.

The way I've seen this done in select() based servers is by linearly traversing the interest set during each iteration of the event loop and purge the inactive connections there. This is not a problem in select because you already have to do this traversal anyways, but I use epoll() precisely to avoid having to do this. If I do this, epoll is no better than select.

我也研究了套接字选项,发现最接近的是SO_RCVTIMEO,如果它等待的时间超过指定的时间,它将使read()/recv()返回错误.但是,由于我正在使用I/O复用,并且套接字处于非阻塞模式,因此不会有任何意义,因为套接字不会阻塞.

I've also looked into socket options, the closest thing I found was SO_RCVTIMEO, which makes read()/recv() return an error if it's been waiting more than the specified time. But since I'm working with i/o multiplexing and the sockets are in nonblock mode this makes no sese because the sockets don't block.

对于解决此问题的任何见解,我将不胜感激.非常感谢.

I would appreciate any insight on how to solve this. Thank you very much.

推荐答案

由于您知道每个套接字的last_active时间,因此您可以计算下一个套接字应超时的时间(假设在此时间内不再发生I/O)过渡期),然后将超时参数传递给epoll_wait()使其在那时唤醒,因此您可以执行连接关闭.

Since you know the last_active time for each socket, you can compute the time at which the next socket should be timed out (assuming no more I/O happens in the interim period) and pass in a timeout argument to epoll_wait() to cause it to wake up at that time so you can perform the connection-close.

这剩下了问题的另一部分-您希望能够执行该计算,而不必在事件循环的每次迭代中都遍历所有套接字.

That leaves the other part of the problem -- you want to be able to perform that computation without iterating across all of the sockets on every iteration of your event loop.

您可以通过维护以下数据结构(例如优先级队列)来做到这一点支持以有效的方式(例如O(1)或O(log(N)))查找最低优先级的元素.在这种情况下,您可以使用套接字的last_active值作为其优先级值.然后,在每次事件迭代之前,循环,请查阅数据结构以找出优先级最低的套接字(又名哪个套接字将是下一个超时的套接字,如果没有进一步的流量发生,则需要断开连接),然后使用该套接字来设置优先级epoll_wait()超时.

You can do that by maintaining a data structure (such as a priority queue) that supports finding the lowest-priority element in an efficient (e.g. O(1) or O(log(N)) manner. In this case you can use the socket's last_active value as its priority-value. Then before each iteration of your event-loop, you consult the data structure to find out which socket has the lowest-priority (aka which socket will be the next one to time out and need to be disconnected, if no further traffic occurs on it), and use that to set your epoll_wait() timeout.

请注意,为了维护数据结构,您需要在套接字每次发送或接收数据时进行更新(通过从结构中删除套接字然后重新插入,以调整其优先级以反映其新活动) (具有更新的/当前的last_time/priority值),但是它也是O(log(N))操作,因此开销不应太高.

Note that in order to maintain the data structure you'll need to update it every time a socket sends or receives data (to adjust its priority to reflect its fresh activity, by removing the socket from the structure and then re-inserting it with an updated/current last_time/priority value), however that is also a O(log(N)) operation so the overhead shouldn't be too high.

这篇关于在基于epoll的服务器中超时空闲连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆