我正在构建一个可以接受和处理多个客户端连接的Web服务器。我正在使用select()
。
现在正在进行,如果某个特定的连接套接字没有任何活动(发送或recv),我想关闭它。因此,如果一段时间内没有来自连接客户端的请求,我将关闭套接字。有多个这样的连接套接字,我需要对每个套接字进行监控。
我需要此功能来创建持久连接,因为我的网络服务器必须支持HTTP 1.1
这样做的最佳方式是什么?
答案 0 :(得分: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.
}
答案 1 :(得分:1)
如果您正在使用线程和阻塞模式,您只需要在套接字上设置合适的SO_RCVTIMEOUT,当read()
使用errno == EAGAIN/EWOULDBLOCK
返回-1时,超时已经发生,所以你只需关闭套接字并退出线程。
如果您使用的是select()
,那就更复杂了。 Adam Rosenfield的建议在表面看起来似乎有道理,但实际上,如果其他套接字足够忙,select()
超时可能根本不会发生,或者至少在套接字实际变得太死之后不会发生很多分钟。如果要严格执行超时,就像在服务器中那样,必须将最后读取时间与每个套接字关联,并在select()
循环的底部迭代fd
设置挑选那些 not 准备好的fds,检查他们的上次阅读时间,并关闭那些已经死亡的时间。