4

我正在构建一个可以接受和处理多个客户端连接的网络服务器。我正在使用select()这个。
现在,在此过程中,如果特定连接的套接字上没有任何活动(发送或接收),我想关闭它。因此,如果一段时间内没有来自已连接客户端的请求,我将关闭套接字。有多个这样的连接套接字,我需要对每个套接字进行监视。

我需要这个功能来创建持久连接,因为我的网络服务器必须支持 HTTP 1.1

做这个的最好方式是什么?

4

2 回答 2

1

我建议将调用超时设置为select下一个套接字超时之前的最短时间。然后,如果超时,关闭空闲套接字,然后重复。像这样的伪代码:

timeout = default_timeout;
foreach(socket s)
{
    timeout = min(timeout, (s.last_send_or_recv_time + IDLE_TIMEOUT - now()));
}

result = select(..., timeout);
if(result == 0)
{
    foreach(socket s)
    {
        if(now() - s.last_send_or_recv_time >= IDLE_TIMEOUT)
        {
            close(s);
            remove_from_socket_list(s);
        }
    }
}
else
{
    // Handle received data, update last_send_or_recv_time, etc.
}
于 2012-09-05T20:05:05.837 回答
1

如果您使用线程和阻塞模式,您只需要在套接字上设置一个合适的 SO_RCVTIMEOUT ,当您read()返回 -1 时errno == EAGAIN/EWOULDBLOCK,超时已经发生,所以您只需关闭套接字并退出线程。

如果你使用select()它会更复杂。Adam Rosenfield 的建议从表面上看似乎是合理的,但实际上,如果其他套接字足够忙,则select()超时可能根本不会发生,或者至少在套接字实际上变得太死后的几分钟内不会发生。如果您想严格执行超时,就像在服务器中应该的那样,您必须将最后读取时间与每个套接字相关联,并且在select()循环的底部,遍历fd集合,挑选出那些准备好的 fd,检查他们的最后阅读时间,并关闭那些太死的人。

于 2012-09-06T02:08:04.673 回答