HTTP如何判定文件大小

如何才能确定http实体的文件长度呢?大致有下面四种情况:
    * 任何不含有消息体的消息(如1XXX、204、304等响应消息和任何头(HEAD,首部)请求的响应消息),总是由一个空行(CLRF)结束。


    * 如果消息使用媒体类型“multipart/byteranges”,并且transfer-length 没有另外指定,那么这种自定界(self-delimiting)媒体类型定义transfer-length 。除非发送者知道接收者能够解析该类型,否则不能使用该类型。


    * 由服务器关闭连接确定消息长度。(注意:关闭连接不能用于确定请求消息的结束,因为服务器不能再发响应消息给客户端了。)


    * 如果出现了Content-Length头字段,它的值表示entity-length(实体长度)和transfer-length(传输长度)。如果这两个长度的大小不一样(i.e.设置了Transfer-Encoding头字段),那么将不能发送Content-Length头字段。并且如果同时收到了Transfer-Encoding字段和Content-Length头字段,那么必须忽略Content-Length字段。


    * 如果出现了Transfer-Encoding头字段 并且值为非“identity”,那么transfer-length由“chunked” 传输编码定义,除非消息由于关闭连接而终止。

 

情况1和情况2这里就不具体说明了,这里依次说明下后面三种:

 

利用tcp连接断开获取文件长度:
    在HTTP/1.0时代,http服务器通常是使用短链接模式,一个get请求,一个tcp连接,数据发送完毕,服务器自动shutdown连接,客户端的read自然就可以返回了(linux里是-1,windows是0),这样自然就知道文件的边际和长度。不过这在HTTP/1.1时代就不管用了,服务器在客户端活跃期或是一定时间的空闲内是不会切断tcp连接的,客户的多次get,是通过同一个tcp连接传送,这就意味客户端不可能通过read返回-1来判断一个http文件传送完了,read在传送完一个文件后,如果你再read,只会堵塞在那里。这时候客户必须自己判断哪里是文件的边界。当然依赖tcp断开来判定文件长度还有个问题,就是一旦网络状况不好,

Content-Length判定大小:
    针对静态页面,图片或其他可以实现确定大小的文件,http服务器会在http头中加入content-length,并写入文件的大小。客户端只需要读取文件头,就可以获取大小。不过现在大部分网站都是基于动态技术,网页的大小,尤其复杂页面的大小,服务器很难马上就知道,如果等待页面完全生成再发送,就使得延迟增加,这对客户体验和服务器的吞吐量是有影响的,这就需要下面的chunk技术了。

chunked编码获取文件大小:
    服务器通过chunked技术可以生成一部分发送一部分,比如可以先发送静态的框架部分,再发送动态的具体内容。简单来说chunked编码,就是将整个文件分块,每个块前面加上块的大小,最后以一个空的快的结束(也不是真的没内容)。
    Chunk编码的格式如下:
    Chunked-Body = *chunk
                   "0" CRLF
                   footer
                   CRLF
    chunk = chunk-size [ chunk-ext ] CRLF
            chunk-data CRLF
    这里的*chunk代表0-任意个chunk块,每个chunk块有两部分组成,第一部分包括块大小,块单位(一般不填),换行(0x0d0a),第二部分包括块的数据,然后以一个空行结束。
    最后以块大小为“0”的空块结束,实际上空块是包含footer的,这是一些元数据,不理会也可以。结尾也是一个空行。

下面是Wireshark对某个网站的数据过滤:

 

image

posted @ 2010-12-30 15:51  hjtc  Views(4550)  Comments(0Edit  收藏  举报