Web 服务器 HTTP1.1 上的持久连接

Posted

技术标签:

【中文标题】Web 服务器 HTTP1.1 上的持久连接【英文标题】:Persistent Connection on a web server HTTP1.1 【发布时间】:2013-06-21 16:54:50 【问题描述】:

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

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

其中 tv 是一个结构时间值。这也不起作用。

有什么建议吗?

【问题讨论】:

【参考方案1】:

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

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

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

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

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

【讨论】:

【参考方案2】:

最简单的解决方案可能是为每个连接保留一个 last-time-request-received,然后定期检查该时间,如果太久则关闭连接。

【讨论】:

以上是关于Web 服务器 HTTP1.1 上的持久连接的主要内容,如果未能解决你的问题,请参考以下文章

【小白学爬虫笔记】持久连接、非持久连接

2016/9/26复习支持点

C套接字HTTP 1.1持久连接服务器何时应关闭套接字?

Android 上的持久 HttpURLConnections

HTTP1.0和HTTP1.1的区别

http1.0与http1.1的区别