HTTP Keep-Alive模式客户端与服务器如何断定传输完成

长链接是什么

咱们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每一个请求/应答客户和服务器都要新建一个链接,完成 以后当即断开链接(HTTP协议为无链接的协议);当使用Keep-Alive模式(又称持久链接、链接重用)时,Keep-Alive功能使客户端到服 务器端的链接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了创建或者从新创建链接。html

服务器如何知道已经彻底接受客户端发送的数据

Content-Length 是一个实体消息首部,用来指明发送给接收方的消息主体的大小,即用十进制数字表示的八位元组的数目。浏览器

客户端如何知道已经彻底接受服务端发送的数据

  • 在HTTP 1.0 短链接中客户端发送一个小请求,服务器响应以所指望的信息(例如一个html文件或一副gif图像)。服务器一般在发送回所请求的数据以后就关闭链接。这样客户端读数据时会返回EOF(-1),就知道数据已经接收彻底了。
  • 消息首部字段Conent-Length
  • 消息首部字段Transfer-Encoding

Transfer-Encoding

当客户端向服务器请求一个静态页面或者一张图片时,服务器能够很清楚的知道内容大小,而后经过Content-length消息首部字段告诉客户端须要接收多少数据。可是若是是动态页面等时,服务器是不可能预先知道内容大小,这时就可使用Transfer-Encoding:chunk模式来传输数据了。即若是要一边产生数据,一边发给客户端,服务器就须要使用"Transfer-Encoding: chunked"这样的方式来代替Content-Length。服务器

chunk编码将数据分红一块一块的发生。Chunked编码将使用若干个Chunk串连而成,由一个标明长度为0的chunk标示结束。每一个Chunk分为头部和正文两部分,头部内容指定正文的字符总数(十六进制的数字)和数量单位(通常不写),正文部分就是指定长度的实际内容,两部分之间用回车换行(CRLF)隔开。在最后一个长度为0的Chunk中的内容是称为footer的内容,是一些附加的Header信息(一般能够直接忽略)。ide

Transfer-Encoding 是一个用来标示 HTTP 报文传输格式的头部值。尽管这个取值理论上能够有不少,可是当前的 HTTP 规范里实际上只定义了一种传输取值——chunked。工具

若是一个HTTP消息(请求消息或应答消息)的Transfer-Encoding消息头的值为chunked,那么,消息体由数量未定的块组成,并以最后一个大小为0的块为结束。ui

每个非空的块都以该块包含数据的字节数(字节数以十六进制表示)开始,跟随一个CRLF (回车及换行),而后是数据自己,最后块CRLF结束。在一些实现中,块大小和CRLF之间填充有白空格(0x20)。this

最后一块是单行,由块大小(0),一些可选的填充白空格,以及CRLF。最后一块再也不包含任何数据,可是能够发送可选的尾部,包括消息头字段。消息最后以CRLF结尾。编码

一个示例响应以下:code

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the data in the first chunk

1A
and this is the second one
0

注意:htm

  • chunked 和 multipart 两个名词在乎义上有相似的地方,不过在 HTTP 协议当中这两个概念则不是一个类别的。multipart 是一种 Content-Type,标示 HTTP 报文内容的类型,而 chunked 是一种传输格式,标示报头将以何种方式进行传输。
  • chunked 传输不能事先知道内容的长度,只能靠最后的空 chunk 块来判断,所以对于下载请求来讲,是没有办法实现进度的。在浏览器和下载工具中,偶尔咱们也会看到有些文件是看不到下载进度的,即采用 chunked 方式进行下载。
  • chunked 的优点在于,服务器端能够边生成内容边发送,无需事先生成所有的内容。HTTP/2 不支持 Transfer-Encoding: chunked,由于 HTTP/2 有本身的 streaming 传输方式(Source:MDN - Transfer-Encoding)。

transfer-coding与Content-Length

其实,上面2中方法均可以概括为是如何判断http消息的大小、消息的数量。RFC 2616对消息的长度总结以下:一个消息的transfer-length(传输长度)是指消息中的message-body(消息体)的长度。当应用了transfer-coding(传输编码),每一个消息中的message-body(消息体)的长度(transfer-length)由如下几种状况决定(优先级由高到低):

  • 任何不含有消息体的消息(如1XXX、20四、304等响应消息和任何头(HEAD,首部)请求的响应消息),老是由一个空行(CLRF)结束。
  • 若是出现了Transfer-Encoding头字段 而且值为非“identity”,那么transfer-length由“chunked” 传输编码定义,除非消息因为关闭链接而终止。
  • 若是出现了Content-Length头字段,它的值表示entity-length(实体长度)和transfer-length(传输长度)。若是这两个长度的大小不同(i.e.设置了Transfer-Encoding头字段),那么将不能发送Content-Length头字段。而且若是同时收到了Transfer-Encoding字段和Content-Length头字段,那么必须忽略Content-Length字段。
  • 若是消息使用媒体类型“multipart/byteranges”,而且transfer-length 没有另外指定,那么这种自定界(self-delimiting)媒体类型定义transfer-length 。除非发送者知道接收者可以解析该类型,不然不能使用该类型。
  • 由服务器关闭链接肯定消息长度。(注意:关闭链接不能用于肯定请求消息的结束,由于服务器不能再发响应消息给客户端了。)

为了兼容HTTP/1.0应用程序,HTTP/1.1的请求消息体中必须包含一个合法的Content-Length头字段,除非知道服务器兼容HTTP/1.1。一个请求包含消息体,而且Content-Length字段没有给定,若是不能判断消息的长度,服务器应该用用400 (bad request) 来响应;或者服务器坚持但愿收到一个合法的Content-Length字段,用 411 (length required)来响应。

全部HTTP/1.1的接收者应用程序必须接受“chunked” transfer-coding (传输编码),所以当不能事先知道消息的长度,容许使用这种机制来传输消息。消息不该该够同时包含 Content-Length头字段和non-identity transfer-coding。若是一个消息同时包含non-identity transfer-coding和Content-Length ,必须忽略Content-Length 。

相关文章
相关标签/搜索