HTTP协议之连接

HTTP连接

1 持久连接

1.1目的

在没有持久连接之前,为获取每一个URL指定的资源都必须建立了一个独立的TCP 连接,这就加重了HTTP服务器的负担,易引起互联网的阻塞。嵌入图片与其它相关数据通常使用户在短时间内对同一服务器进行多次请求。

HTTP持久连接有着诸多的优点:

1、通过建立与关闭较少的TCP连接,不仅节省了路由器与主机(客户端,服务器,代理,网关,隧道或缓存)的CPU时间,还节省了主机用于TCP协议控制块(TCP protocol control blocks)的内存

2HTTP请求和响应能在连接上进行管线请求方式。管线请求方式能允许客户端执行多次请求而不用等待每一个请求的响应,并且此时只有一个TCP连接被使用,从而提高了效率,减少了时间。

3网络阻塞会被减少,这是由于减少了因TCP连接产生的包的数量并且也由于允许TCP有充分的时间去决定网络阻塞的状态。

4、因为无须在创建TCP连接时的握手上耗费时间,而使后续请求的等待时间减少。

1.2 实现方式

HTTP/1.1与早期HTTP版本的一个显著区别在于持久连接HTTP/1.1缺省方式。也就是说,除非另有指定,客户端总应当假定服务器会保持持久连接,即便在收到服务器的出错响应时也应如此。

持久连接提供了一种可以由客户端或服务器通知终止TCP连接的机制。利用Connection头域可以产生终止连接信号。一旦出现了终止连接的信号,客户端便不可再向此连接提出任何新请求。

1.2.1 协商(Negotiation)

除非请求里Connection头域中包含“close”连接标记(connection-token),HTTP/1.1服务器总可以认为HTTP/1.1 客户端想要维持持久连接(persistent connection)。如果服务器想在发出响应后立即关闭连接,它应当发送一个含“close”的Connection头域。

一个HTTP/1.1客户端可能期望连接一直保持开着,但这必须是基于服务器响应里是否包含一个Connection头域并且此头域里是否包含“close”。如果客户端不想再继续维持连接来发送更多请求,那么它应发送一个值为“close”的Connection头域。

如果客户端或服务器中的任一方在Connection头域里包含“close”,那么那个请求就成为这个连接的最后一个请求。

1.2.2 管线(pilelining)

支持持久连接(persistent conncetion)的客户端可以以管线的方式发送请求(即无须等待响应而发送多个请求)。服务器必须按接收请求的顺序发送响应。

假定以持久连接方式进行连接,并且假定在连接建立后进行管线方式请求的客户端应该准备去重新尝试连接如果首次管线请求方式尝试失败。如果客户端重新去尝试连接,那么,只有在客户端知道连接是持久连接之后,客户端才能进行管线发送请求。如果服务器在响应所有对应的请求之前关闭了连接,客户端必须准备去重新发送请求。

客户端不应该利用非等幂的方法或者非等幂的方法序列进行管线方式的请求。否则一个过早的传输层连接的终止可能会导致不确定的结果。希望发送非等幂方法请求的客户端只有接收了上次它发出请求的响应后才能再次发送请求给服务器。

1.2.3 代理(Proxy Servers)

代理是非常重要的,因为代理正确地实现了Connection头域的属性。

代理必须分别向它相连的客户端或源服务器(或其他的代理)指明持久连接。每一个持久连接只能应用于一个传输层连接。

1.2.4常见问题

服务器通常有一个时限值,超过一定时间即不再维持处于非活动的连接。代理会选一个较高的值,因为客户端很可能会与同一服务器建立多个连接。持久连接方式的采用对于客户端与服务器来说均未提出任何必须存在超时或给定多长时间的要求。

当客户端或服务器希望超时时, 它应该优雅的去关闭传输连接。客户端与服务器端应始终注意对方是否终止了传输层连接,并适当的予以响应。若客户端或服务器未能及时检测到对方已终止了连接,将会造成不必要的网络资源浪费。

客户端,服务器,或代理可能在任意时刻会终止传输连接。比如,客户端可能正想发出新的请求,而此时服务器却决定关闭“闲置”的连接。在服务器看来,连接已经因为闲置被关闭了,但客户端认为我正在请求。

这表明客户端,服务器与代理必须有能力从连接的异步终止事件中恢复。只要请求是等幂的,客户端软件应该能重新打开传输层连接并重试传输遗弃的请求序列而不需要用户进行去交互。对非等幂方法的请求就不能自动重试请求,尽管用户代理(user agent)可能提供一个人工操作去重试这些请求。用户代理(user-agent)对应用程序语义理解的确认应该替代用户的确认。如果再次重试请求序列失败,那么就不能再进行自动重试请求了。

服务器尽可能应该至少在每次连接中响应一个请求。除非出于网络或客户端的故障,服务器不应在传送响应的中途断开连接。

使用持久连接的客户端应限制与某一服务器同时连接的个数。单用户客户端不应与任一服务器或代理保持两个以上的连接。代理应该与其它服务器或代理之间维护2*N个连接,其中N是同时在线的用户数。这些准则是为了改善响应时间和和避免阻塞。

2 消息传送的要求

2.1 持久连接与流量控制

HTTP/1.1服务器应保持持久连接并使用TCP流量控制机制来解决临时过载,而不是在终止连接后指望客户端的重试。后一方法会恶化网络阻塞。

2.2 监视连接中出错状态的消息

HTTP/1.1(或更新)客户端应该当在发送请求的消息主体时同时监视网络连接是否处于出错状态。若客户端发现了错误,它应当立即停止消息主体的的传送。若消息主体是以块传输编码方式发送的,可以用长度为零的块和空尾部(trailer)来提前标记报文结束。若消息主体之前有Content-Length头域,那么客户端必须关闭连接。

2.3 100状态码的用途

100状态码的目的在于允许客户端,在发送此请求消息主体前,判定服务器是否愿意接受发送消息的主体(基于请求的头域)。 在有些情况下,如果服务器拒绝查看消息主体,这时客户端发送消息主体是不恰当的或会大大降低效率。

HTTP/1.1客户端的要求:

1、若客户端想要在发送请求消息主体之前等候100(继续)响应,则它必须发送一个Expect请求头域,并且值是“100-continue”。

2、如果此客户端不打算发送带消息主体的请求,客户端不能发送一个值是“100-continue”的Expect请求头域。

由于存在旧实现,协议允许二义性的情形存在,这在客户端在发送“Expect:100-continue”后而不一定要接收一个417(期望失败)状态码或者100(继续)状态码时。因此,当一个客户端发送Expect请求头域给一个源服务器(可能通过代理),此服务器也没有以100(继续)状态码响应,那么客户端不应该在发送请求消息的主体前无限等待。

HTTP/1.1源服务器的要求:

1、当接收一个包含值为“100-contitue”的Expect请求头域的请求时,源服务器必须或者以100(继续)状态码响应从而继续从输入流里接收数据,或者以一个最终的状态码响应。源服务器不能在发送100(继续)状态码响应之前接收请求主体。如果服务器以一个终结状态码响应后,它可能会关闭传输层连接或者它也可能会继续接收或遗弃剩余的请求。但是既然它返回了一个终结状态码的响应,它就不能再去执行那个请求的方法(如:POST方法,PUT方法)。

2如果请求消息不含值为“100-continue”的Expect请求头域, 源服务器不应发送100(继续)响应,并且,当请求来自HTTP/1.0(或更早)的客户端时,服务器也不得发送100(继续)响应。对此规定有一例外:为了与RFC 2068兼容,源服务器可能会发送一个100(继续)状态响应以响应HTTP/1.1PUTPOST请求,虽然这些请求中没有包含值为“100-continue”的Expect请求头域。这个例外的目的是为了减少任何客户端因为等待100(继续)状态响应的延时,但此例外只能应用于HTTP/1.1请求,并不适合于其他HTTP版本的请求。

3、若源服务器已经接收到部分或全部请求的消息的主体,源服务器可以不需要发100(继续)响应。

4、一旦请求消息主体被接收和被处理,发送100(继续)响应的源服务器必须最终能发送一个终结状态响应,除非源服务器过早切断了传输层连接。

5、若源服务器接收到不含值为“100-contitue”的Expect请求头域的请求,但该请求含有请求消息主体,而服务器在从传输层连接上接收整个请求消息主体前返回一个终结状态响应,那么此源服务器不能关闭传输层连接直到它接收了整个请求或者直到客户端关闭了此连接。否则客户端可能不会信任接收此响应消息。然而,这一要求不应该被解释为防止服务器免受拒绝服务攻击,或者防止服务器被客户端攻击。

HTTP/1.1代理的要求:

1、若代理接到一个请求,此请求包含值为“100-continue”的Expect请求头域,并且代理可能不能确定下一站服务器是否遵循HTTP/1.1或更高版协议,那么它必须转发此请求时包含此Expect头域

2、若代理知道下一站服务器版本是HTTP/1.0或更低,则它不能转发此请求,并且它必须417(期望失败)状态响应

3、代理应当维护一个缓存,以记录最近访问下一站点服务器的HTTP版本号

4、若接收到的请求来自于版本是HTTP/1.0(或更低)的客户端,并且此请求不含值为“100-continue”的Expect请求头域,那么代理不能转发100(继续)响应。 这一要求可覆盖1xx响应转发的一般规则。

2.4 服务器过早关闭连接时客户端的行为

如果HTTP/1.1 客户端发送一条含有消息主体的请求消息,但不含值为“100-continue”的Expect请求头域,并且如果客户端没有直接与HTTP/1.1源服务器相连,并且客户端在接收到服务器的状态响应之前看到了连接的关闭,那么客户端应该重试此请求。在重试时,客户端可以利用下面的算法来获得可靠的响应。

1、向服务器发起一新连接。

2、发送请求头域。

3、初始化变量R,使R的值为通往服务器的往返时间的估计值(比如基于建立连接的时间),或在无法估计往返时间时设为一常数值5秒。

4、计算T=R*2**N),N为此前重试请求的次数。

5、等待服务器出错响应,或是等待T秒(两者中时间较短的)。

6、若没等到出错响应,T秒后发送请求的消息主体。

7、若客户端发现连接被提前关闭,转到第1步,直到请求被接受,接收到出错响应,或是用户因不耐烦而终止了重试过程。

在任意点上,客户端如果接收到服务器的出错响应,客户端

1、不应再继续发送请求

2、应该关闭连接如果客户端没有完成发送请求消息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值