c - 如何使用 poll() 检测超时的客户端?

标签 c sockets networking timeout

我正在编写一个非 fork 服务器,使用 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 个客户端正在发送和接收数据,但是一个客户端是静默的,没有数据进出,即。只是占用服务器上的一个套接字。

现在,问题是 poll() 无法识别这一个特定的客户端,因为所有其他 14 个客户端都在提供数据,所以 poll() 说,没问题。

您将如何通过检测此静默客户端并关闭其连接来解决此问题?

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

然后我每 60 秒使用一个警报信号,并运行 lastseen 数组,将它们的时间戳与当前时间戳进行比较,并拆除所有空闲时间超过 60 秒的连接。

或者也许一个线程可以做同样的事情来避免信号。你有什么建议来解决这个问题?

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

最佳答案

检测与套接字相关的错误不是轮询的工作。它所做的一切表明一个或多个套接字是否准备好进行读写操作。如果任何等待的套接字发生错误,则 poll 将该套接字标记为就绪(实际上它由操作系统标记)并且 POLLERR 标志在 revents 字段中指示。

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

也可以考虑使用 epoll - 对于一次轮询中的大量套接字,它要快得多。并且对于最近超时的选择,您可以使用堆数据结构。因此,您可以管理所有具有 O(log n) 执行时间的套接字。

关于c - 如何使用 poll() 检测超时的客户端?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40070698/

相关文章:

c - Linux 下的 TCP 客户端/服务器

C - printf 输出根据后续代码而变化

c - 想要从C中的结构体内存中访问结构体指针类型的数据

javascript - 在 Jsctypes 中将 char * 从 javascript 传递到 c 并将 char * 从 c 返回到 javascript

将多个 OpenCL 缓冲区组合成一个大缓冲区

java - 流写入异常

linux - 如何将名称添加到命名空间?

java - 使用 UDP 的服务器-客户端

java - 如何将 Android 程序套接字到本地主机服务器?

c - malloc 导致 SIGSEGV :Segmentation fault