1、Connection首部字段:允许发送端指定只与当前连接有关的选项。
该字段有一个由逗号分隔的连接标签列表。3种不同类型的标签:
# 3种标签:HTTP首部字段名、close(本次事务结束后关闭此连接)、用作非标准选项的任意值 Connection: Meter, close, bill-my-credit-card Meter: max-uses=3, max-refuses=6, dont-report
HTTP应用程序在将报文转发给下一站之前(如代理),删除Connection首部以及Connection中列出的所有首部。将逐跳首部(只与一条特定连接有关,不能被转发的首部)名放入Connection首部被称为“对首部的保护”,可以防止无意中对本地首部的转发。此外,还有一些不能作为Connection首部值列出的逐跳首部:Proxy-Authenticate、Proxy-Connection和Transfer-Encoding和Upgrade等。
至于为何要这么做,请参考下文的“哑代理/盲中继问题”。
2、持久连接
HTTP/1.1(以及HTTP/1.0的各种增强版本)允许HTTP设备在事务处理结束之后将TCP连接保持在打开状态,以便为未来的HTTP请求重用现有的连接。这种连接称为持久连接。非持久连接会在每个事务结束之后关闭。
重用连接可以避免缓慢的连接建立阶段。而且已经打开的连接还可以避免慢启动的拥塞适应阶段,以便更快速地进行数据的传输。
持久连接有两种类型:比较老的HTTP/1.0+ “keep-alive”连接,以及现代的HTTP/1.1 “persistent”连接。
1)HTTP/1.0+ keep-alive连接
这些早期的持久连接受到了一些互操作性设计方面问题的困扰,这些问题在后期的HTTP/1.1版本中都得到了修正,但很多客户端和服务器仍然在使用这些早期的keep-alive连接。
(1)使用
keep-alive已经不再使用了,而且在当前的HTTP/1.1规范中也没有对它的说明了。但浏览器和服务器对keep-alive握手的使用仍然相当广泛。
客户端可以通过包含Connection: Keep-Alive首部请求将一条连接保持在打开状态。如果服务器同意,就在响应中包含相同的首部。如果响应中没有Connection: Keep-Alive首部,客户端就认为服务器不支持keep-alive,会在发回响应报文之后关闭连接。
(2)选项
Keep-Alive首部只是请求将连接保持在活跃状态。发出keep-alive请求之后,客户端和服务器并不一定会同意进行keep-alive会话。它们可以在任意时刻关闭空闲的keep-alive连接,并可随意限制keep-alive连接所处理事务的数量。
可以用Keep-Alive首部中指定的、由逗号分隔的选项来调节keep-alive的行为:
Connection: Keep-Alive # Keep-Alive首部只有在提供Connection: Keep-Alive时才能使用 Keep-Alive: max=5, timeout=120 # timeout:估计了服务器希望将连接保持在活跃状态的(空闲)时间。不是一个承诺值
# max:估计了服务器还希望为多少个事务保持此连接的活跃状态。不是一个承诺值
另外,Keep-Alive首部还可支持任意未经处理的属性(主要用于诊断和调试),语法为name [=value]。
(3)一些规则
在HTTP/1.0中,keep-alive并不是默认使用的。客户端必须发送一个Connection: Keep-Alive请求首部来激活keep-alive连接。
Connection: Keep-Alive首部必须随所有希望保持持久连接的报文一起发送。如果客户端没有发送Connection: Keep-Alive首部,服务器就会在那条请求之后关闭连接。
客户端探明响应中没有Connection: Keep-Alive响应首部,就可以知道服务器发出响应之后是否会关闭连接了。
(4)哑代理/盲中继问题
如果代理不理解Connection首部,而且不知道在转发到下一站之前将该首部删除,则会出现问题。很多老的或简单的代理都是盲中继(blind relay),它们只是将字节从一个连接转发到另一个连接中去,不对Connection首部进行特殊的处理。
假设有一个Web客户端正通过一个作为盲中继使用的哑代理与Web服务器进行对话:
I、Web客户端向代理发送带有Connection: Keep-Alive首部的请求,之后等待响应,以确定对方是否同意使用keep-alive连接;
II、哑代理收到请求,但它并不理解Connection首部和keep-alive,只是将报文一字不漏地转发给服务器;
III、Web服务器收到带有Connection: Keep-Alive首部的请求时,会误以为代理希望进行keep-alive对话。于是它同意了,回送了一个Connection: Keep-Alive响应首部;
IV、哑代理将响应报文转发给客户端。客户端于是认为代理同意进行keep-alive对话。所以,此时客户端和服务器都认为它们在与代理进行keep-alive对话,但代理却对keep-alive一无所知;
V、由于代理不理解keep-alive,在完成一次事务之后,它分别(半)关闭了与客户端的连接和与服务器的连接。这样客户端发出的下一次请求就无法收到来自服务器的响应了。
为避免这个问题,才引入上文提及的逐跳首部。
(5)Proxy-Connection首部:解决(一个)盲中继带来的问题
浏览器向代理发送Proxy-Connection首部,而不是Connection首部。如果代理是盲中继,它会将Proxy-Connection首部转发给Web服务器,服务器将忽略此首部,不会带来任何问题。如果是个聪明的代理(能理解持久连接的握手动作),就用Connection首部取代Proxy-Connection首部,再发送给服务器,以收到预期的效果。
如果在哑代理的任意一侧还有一个聪明的代理,则盲中继问题又会再次出现了。
2)HTTP/1.1持久连接
HTTP/1.1逐渐停止了对keep-alive连接的支持,用持久(persistent)连接取代了它。两者的目的相同,但后者的工作机制更优一些。
与HTTP/1.0+的keep-alive连接不同,HTTP/1.1持久连接在默认情况下是激活的。要在事务处理结束之后将连接关闭,HTTP/1.1应用程序必须向报文中显式地添加一个Connection: close首部。但是,客户端和服务器仍然可以随时关闭空闲的连接。不发送Connection: close并不意味着服务器承诺永远将连接保持在打开状态。
(1)一些规则
只有当连接上所有的报文都有正确的、自定义报文长度时——即实体主体部分的长度都和相应的Content-Length一致,或者是用分块传输编码方式编码的——连接才能持久保持。
参考资料:
《HTTP权威指南》
不断学习中。。。