我正在用c编写一个TCP服务器,该服务器使用epoll()I / O复用来管理并发连接。我想使空闲时间超过允许时间的连接超时。
到目前为止,我保留了与每个连接关联的last_active time_t变量,该变量在事件处理程序中更新为当前时间。在此之前,我检查自上一次事件以来是否已超过允许的时间,如果是,则终止连接。
到目前为止还不错,但这并不是我真正想要的,因为超时仅在第一个超时事件中触发,但是如果连接保持不活动状态,我的代码只有在其变为“活动”状态时才会检测到它再次。
我在基于select()的服务器中看到的方法是在事件循环的每次迭代期间线性遍历兴趣集并清除那里的非活动连接。在选择中这不是问题,因为无论如何您都已经必须执行此遍历,但是我正好使用epoll()来避免这样做。如果执行此操作,则epoll并不比select更好。
我还研究了套接字选项,发现最接近的是SO_RCVTIMEO,如果它等待的时间超过指定的时间,它将使read()/ recv()返回错误。但是,由于我正在使用I / O多路复用,并且套接字处于非阻塞模式,因此不会有任何意义,因为套接字不会阻塞。
对于解决此问题的任何见解,我将不胜感激。非常感谢。
答案 0 :(得分:1)
由于您知道每个套接字的last_active时间,因此您可以计算下一个套接字应超时的时间(假设在过渡期内不再发生I / O)并将超时参数传递给{{1 }}使其在那时唤醒,因此您可以执行连接关闭。
这剩下了问题的另一部分-您希望能够执行该计算,而不必在事件循环的每次迭代中都遍历所有套接字。
您可以通过维护支持以有效的方式(例如O(1)或O(log(N)))查找最低优先级元素的数据结构(例如priority queue)来实现此目的。在这种情况下,您可以将套接字的last_active值用作其优先级值。然后,在每次事件循环迭代之前,您都要查询数据结构以找出哪个套接字的优先级最低(又名哪个套接字是优先级最高的套接字)。超时并且需要断开连接(如果没有更多流量发生),请使用该超时来设置您的epoll_wait()
超时。
请注意,为了维护数据结构,您需要在套接字每次发送或接收数据时进行更新(通过从结构中删除套接字然后重新插入,以调整其优先级以反映其新活动)它具有更新的/当前的last_time / priority值),但是这也是O(log(N))操作,因此开销不应太高。