2016-10-16 45 views
3

我正在写一个非分岔服务器,使用poll()进行多个同时连接。它工作正常,除了我有问题如何检测超时正确的方式。如何使用poll()检测超时客户端?

比方说,我有以下代码:

#define POLL_SIZE 512 

struct pollfd poll_set[POLL_SIZE]; 
timeout = 60000; // 60 secs 

// setup server_sockfd with socket(), bind(), listen(), ... 

poll_set[0].fd = server_sockfd; 
poll_set[0].events = POLLIN; 
numfds = 1; 

while(1) { 
    rc = poll(poll_set, numfds, timeout); 
    if(rc == 0){ 
     // handle timeout 
    } 

    for(fd_index = 0; fd_index < numfds; fd_index++) { 
     if(poll_set[fd_index].revents & POLLIN) { 
     // accept new connection or handle established connections 
     } 
    } 
} 

假设,我有15个客户端连接,14个客户端发送和接收数据,但一个客户是沉默,没有数据或者从,即。只需占用服务器上的一个套接字即可。现在

,问题是,民意调查()不能当场这个特定的客户端,因为所有其他14个客户端提供数据,所以民调()说,它的确定。

你将如何通过检测这个沉默的客户解决了这个问题,并关闭它的连接?

目前,我还没有更好的,然后创建一个time_t lastseen [POLL_SIZE]数组,并且当从客户端读取数据或发送到客户端时跟踪给定连接的时间戳。

然后我在每60秒,使用报警信号,并通过lastseen阵列运行时,比较其与当前时间戳的时间戳,和拆除每个连接为空闲> 60秒。

或许一个线程可以做,以避免信号是相同的。你有什么建议来解决这个问题?

(请注意,我尝试用libevent的,这是非常好的。但是,我不得不放弃,因为我找不到支持SSL/TLS添加到已经连接的套接字。想想STARTTLS的)

回答

0

检测与套接字相关的错误不是轮询的工作。它所做的只是表明一个或多个套接字是否准备好进行读写操作。如果任何等待的套接字都发生错误,那么在revents字段中指示套接字已准备就绪(实际上由OS标记)和POLLERR标志。

什么时间超时。通常,超时不是传输层错误(因此不会被套接字跟踪)。你需要自己跟踪它。例如,您可以记住上次从套接字读取的时间戳(请参阅clock_gettime(CLOCK_MONOTONIC,...)),并将轮询超时设置为与该套接字相关的所有超时的最小值。超时过期后,您需要检查每个套接字是否过期或者不是。

也可以考虑使用epoll的 - 这是快得多大量调查一个插座。此外,对于选择最近的超时,您可以使用堆数据结构。因此,您可以使用O(log n)执行时间管理所有套接字。

+0

谢谢梅德,然后我会跟踪给定的插座自己的时间戳。比 –

+0

感谢与clock_gettime的提示。顺便说一句。尽管我开发的软件主要在Linux上运行,但我仍想继续支持其他操作系统(例如Freebsd等)支持民意测验。 –