1

我正在尝试使用协议 HTTP1.1 在 Linux 下用 C 语言编写 Web 服务器。我已经对多个请求使用了 select,并且我想实现持久连接,但到目前为止它没有工作,因为我无法正确设置超时。我该怎么做?我想到了 setsockopt 功能:

setsockopt(connsd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv))

其中 tv 是一个结构时间值。这也行不通。

有什么建议么?

4

2 回答 2

1

SO_RCVTIMEO仅在您实际读取数据时才有效。select()不会尊重它。select()在其最后一个参数中采用超时参数。如果您有一个计时器数据结构来组织哪些连接应该按什么顺序超时,那么您可以将最快到超时时间传递给select(). 如果返回值为 0,则表示发生了超时,您应该使所有超时的连接过期。在处理实时连接(并在计时器数据结构中重新设置它们的空闲超时)之后,您应该再次检查是否有任何连接应该在再次调用之前超时select()

您可以使用多种数据结构,但流行的包括计时轮和计时器堆。

计时轮基本上是一个组织为循环缓冲区的数组,其中每个缓冲区位置代表一个时间单位。如果车轮单位是秒,您可以构建一个 300 个元素的数组来表示 5 分钟的时间。有一个粘性索引表示任何计时器最后一次过期,当前位置将是当前时间以数组大小为模。要添加超时,请计算需要超时的绝对时间,以数组大小为模,然后将其添加到该数组位置的列表中。最后一个索引和当前位置之间的所有桶都需要过期。条目过期后,最后一个索引会更新到当前位置。要计算直到下一次到期的时间,

计时器堆基本上是一个优先级队列,其中较早过期的条目比较晚过期的条目具有更高的优先级。非空堆的顶部决定了下次到期的时间。

如果您的应用程序一直在插入大量计时器,然后一直取消它们,那么轮子可能更合适,因为插入轮子并从轮子中移除比插入和移除轮子更有效优先队列。

于 2013-06-21T17:52:07.163 回答
1

最简单的解决方案可能是为每个连接保留最后一次接收请求,然后定期检查该时间,如果时间太长则关闭连接。

于 2013-06-21T16:58:44.817 回答