我正在尝试使用 HTTP1.1 协议(protocol)在 Linux 下用 C 语言编写 Web 服务器。 我已经为多个请求使用了 select,我想实现持久连接,但到目前为止它没有用,因为我无法正确设置超时。我该怎么做?我想到了 setsockopt 函数:
setsockopt(connsd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv))
其中 tv 是一个时间间隔结构。这也不起作用。
有什么建议吗?
最佳答案
SO_RCVTIMEO
只有在您实际读取数据时才会起作用。 select()
不会接受它。 select()
在其最后一个参数中采用超时参数。如果你有一个计时器数据结构来组织哪些连接应该以什么顺序超时,那么你可以将最快的超时时间传递给select()
。如果返回值为 0,则发生超时,您应该终止所有超时连接。在处理实时连接(并在您的定时器数据结构中重新设置它们的空闲超时)之后,您应该再次检查以查看是否有任何连接应该在再次调用 select()
之前超时。
您可以使用各种数据结构,但常用的包括计时轮和计时器堆。
计时轮基本上是一个组织为循环缓冲区的数组,其中每个缓冲区位置代表一个时间单位。如果车轮单位以秒为单位,您可以构造一个 300 个元素的数组来表示 5 分钟的时间。有一个粘性索引表示任何计时器的最后一次过期时间,当前位置将是当前时间对数组大小的模数。要添加超时,请计算需要超时的绝对时间,将其除以数组的大小,然后将其添加到该数组位置的列表中。最后一个索引和已达到超时的当前位置之间的所有桶都需要过期。条目过期后,最后一个索引将更新到当前位置。为了计算到下一次过期的时间,从当前位置开始扫描桶,以找到具有将过期条目的桶。
定时器堆基本上是一个优先级队列,其中较早过期的条目比较晚过期的条目具有更高的优先级。非空堆的顶部决定了下一次到期的时间。
如果您的应用程序一直在插入大量计时器,然后一直取消它们,那么轮子可能更合适,因为插入轮子并从轮子中取出比插入和取出更有效从优先队列中移除。
关于c - Web 服务器 HTTP1.1 上的持久连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17240518/