39

据我了解,HTTP 连接可以是keep-aliveclose.

我向服务器发送了一个 HTTP 请求:

GET /page1/ HTTP/1.1
Host: server.com
Connection: keep-alive

它的回应是:

HTTP/1.1 200 OK
Connection: keep-alive, close

从本质上讲,我相信服务器被窃听是因为类似的响应keep-alive, close是模棱两可的。

但是,作为接收者,我们应该如何处理这样的消息呢?我们应该将此标头值解释keep-alive为orclose吗?

4

4 回答 4

29

TL; DR:Chrome 将此响应标头解释为keep-alive并在 Firefox 关闭每个连接时保持永久连接。

当我试图优化我的网站的页面加载时间时,我偶然发现了这个问题。

在引用的 RFC 中,我没有找到有关如何Connection正确处理标头中的多个条目的任何信息。在我看来,实现可以从两种可能性中进行选择:

  1. 如果有多个条目,您可以选择最适合您需求的条目
  2. 如果有close内部,可以在传输后关闭连接

所以,我需要找出答案。让我们做一些更深入的调查:

我注意到 Chrome 总是发送一个 HTTP/1.1 请求,Connection: keep-alive而我的 Apache 默认配置总是用一个Connection: close标头响应。所以我开始调查并使用 Wireshark 查看 TCP 段。

Chrome 必须获取 14 个元素来显示网站,其中大部分是静态的东西,如图像或 css 文件。它完成了 14 个 TCP 连接,并且花费了很多时间(大约 1.2 秒)。在每次请求图像(例如)之后,都会出现一个FIN标志设置为 1 的 TCP 段。

那么 Chrome 与 Firefox 呢?Chrome 似乎有一个服务器的最大并发连接数为 6。Firefox 具有更精细的配置,并区分持久性(最多 6 个,见 about:config)和非持久性(不同来源的最大数量差异很大)。但是等等...... Chrome 和 Firefox 都发送带有 的 HTTP/1.1 请求标头Connection: keep-alive,因此两者都应限制为 6(因为这是打开持久连接的请求)。

我决定尝试一个简单的技巧,并将以下几行添加到我.htaccess的 web 根文件夹中:

<ifModule mod_headers.c>
Header set Connection keep-alive
</ifModule>

服务器现在响应:

Connection: keep-alive, close

现在我再次查看了 TCP 段:现在从 Chrome 到我的服务器只有 9 个连接,并且只有 3 个FIN标志设置为 1。所以这个技巧似乎奏效了。但是为什么有这3个连接,在数据传输后关闭了连接?X-Powered-By: PHP/5.4.11正如 HTTP 标头所确认的,这些是 PHP 请求。

那么火狐呢?还有那14个请求!

如何解决这个问题并让 fcgi 进程也与 keep-alive 一起工作?

我在 httpd.conf 配置的虚拟主机部分添加了以下几行:

KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100

并删除了添加到.htaccess. 现在服务器没有发送任何令人困惑的 - Connection: keep-alive, close,但只有Connection: keep-alive一切正常!

结论:

连接字段设置为的标头

HTTP/1.1 200 OK
Connection: keep-alive, close

将被 Chrome 解释为keep-aliveFirefox 似乎关闭了每个连接。这似乎取决于实际的实现。

因此,如果您愿意实现一个客户端来处理包含 的响应标头,Connection: keep-alive, close如果您需要多个请求,我建议您尝试使用 keep-alive。可能发生的最糟糕的事情:服务器将关闭连接,您需要再次连接(这正是您可能拥有的另一个选项!)

于 2014-03-03T09:44:29.050 回答
3

这意味着服务器不会做持久连接,并且会在这个请求之后关闭连接。

于 2012-07-12T01:17:21.717 回答
2

答案在RFC 7230 — 6.1。连接。它说:

Connection 标头字段的值具有以下语法:

 Connection        = 1#connection-option
 connection-option = token

在 Internet RFC 用语中,这1#connection-option意味着至少一个且最多任意数量的connection-option. 这意味着可能有多个选项,接收者将在其中选择它喜欢的任何人。这不是模棱两可,这是一种选择。

于 2015-03-02T15:15:58.437 回答
2

您正在使用HTTP/1.1并且正在指定Connection: keep-alive.

默认情况下HTTP/1.1,所有连接都是保持活动状态,并且Connection: keep-alive标头已被弃用,因此您不应该发送它。

Connection: keep-alive是在所谓的HTTP/1.0+日子里使用的一个小技巧。(+代表“使其工作所需的黑客行为”。)

HTTP:O'Reilly 的 Brian Totty、Marjorie Sayer、Sailu Reddy、Anshu Aggarwal、David Gourley 的权威指南中,我们读到:

Keep-alive 已被弃用,并且不再记录在当前的 HTTP/1.1 规范中。然而,浏览器和服务器仍然比较普遍地使用保持活动握手,因此 HTTP 实现者应该准备好与之互操作。

服务器可能正在“互操作”并指责您是多余的。

于 2017-04-17T12:24:20.543 回答