Time out idle connections in epoll based server

风流意气都作罢 提交于 2019-12-23 03:36:11

问题


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.

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.

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.

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.


回答1:


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.

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.

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.



来源:https://stackoverflow.com/questions/51763192/time-out-idle-connections-in-epoll-based-server

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!