一、HTTP协议头:
服务端根据客户端发送的请求头中某些字段自动发送最合适的版本。可以用于这个机制的请求头字段分为两种:Accept字段、其他字段。
请求头字段 |
说明 |
响应头字段 |
Accept-Encoding |
告知服务器采用何种压缩方式 |
Content-Encoding |
比如客户端发送的请求头:
-
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
-
Accept-Encoding:
gzip, deflate, sdch
-
Accept-Language:
zh-CN,zh;q=0.8
Accept:优先接受text/html....,后在接受image/webp...
Accept-Encoding:支持采用gzip、deflate或sdch压缩过的资源
Accept-Language:支持zh-CN和zh两种语言,q表示权重值(0~1)之间
浏览器响应头:
-
Content-Encoding:
gzip
-
Content-Type:
text/html; charset=UTF-8
表示这个文档确切的MIME类型是text/html;文档内容进行了gzip压缩,响应头没有Content-Language字段,通常说明返回版本的语言正好是请求头Accept-Language中权重最高的那个。
1) 接下来我们来详细分析下http压缩的完整过程
a、浏览器发送http request给web服务器,request中有Accept-Encoding:gzip,deflate。
b、Web服务器接到request后,生成原始的Response,其中有原始的Content-Type和Content-Length。
c、Web服务器通过Gzip来对Response进行编码,编码后header中有Content-Type和Content-Length(压缩后的大小),并且增加了Content-Encoding:gzip。然后把Response发送给浏览器。
d、浏览器接到Response后,根据Content-Encoding:gzip来对Response进行编码。获取到原始response后,然后显示出网页。
整个流程图如下:
2)通过fiddler抓包观察
解码前展示:
解码后展示:
二、浏览器支持的三种http传输压缩算法
1)sdch压缩算法
sdch是shared dictionary compression over http的缩写,即通过字典压缩算法对各个页面中相同的内容进行压缩,减少相同的内容传输。如:一个网站中一般都是共同的头部和尾部,甚至一些侧边栏也是共同的。之前的方式每个页面打开的时候这些共同的信息都要重新加载,但使用sdch压缩方式,共同的内容只用传输一次就可以。
sdch主要分为3个部分:首次请求,下载字典,其他请求。
------------首次请求----------
客户端:
Accept-Encoding: sdch
服务端:
Get-Dictionary: /path/to/dict
-----------下载字典-----------
客户端根据Get-Dictionary的值来下载字典,普通的HTTP请求。
-----------其他请求-----------
客户端:
Accept-Encoding: sdch
Avail-Dictionary: xxx
服务器端:
根据Avail-Dictionary的值来进行sdch编码,如果Accept-Encoding里有gzip,这些数据还会被gzip压缩,之后返回。
sdch与ajax+pushState
sdch压缩方式是为了减少相同内容的传输,和ajax+pushState相同都是减少相同内容的传输。sdch是google出的,但pushState是H5的一个标准,目前已经有Chrome和Firefox支持,之后会有越来越多浏览器支持。
2)gzip压缩算法
表示实体采用GNU zip编码,无损压缩算法,用于减少传输报文的大小,不会导致信息损失。效率最高,使用最广泛。
压缩方式:是在一个文本文件中找出类似的字符串,并临时替换他们,使整个文件变小。这种形式的压缩对Web来说非常适合,因为HTML和CSS文件通常包含大量的重复的字符串,例如空格,标签。
gzip可设置压缩比率,取值范围在1(最低)到9(最高)之间,不建议设置太高,虽然有很高的压缩率,但是占用更多的CPU资源。
gzip压缩对图片压缩效果相对较差
a)讲解gzip使用压缩算法的基本原理
gzip对于要压缩的文件,首先使用LZ77算法的一个变种进行压缩,对得到的结果再使用Huffman编码的方法(gzip根据情况,会选择使用静态Huffman编码或者动态Huffman编码)进行压缩。所以明白LZ77算法和Huffman编码的压缩原理,也就明白gzip压缩原理。
a-1)LZ77算法压缩原理
如果文件中有两块内容相同的话,那么只要知道前一块的位置和大小,我们就可以确定后一块的内容。所以我们可以用(两者之间的距离,相同内容的长度)这样一对信息,来替换后一块内容。由于(两者之间的距离,相同内容的长度)这一对信息的大小,小于被替换内容的大小,所以文件得到了压缩。
示例:有一个文件内容a.conf
其中有些部分的内容,前面已经出现过了,下面用()括起来的部分就是相同的部分。
我们使用(两者之间的距离,相同内容的长度)这样一对信息来替换后一块内容
(22, 7)中,22为相同内容块与当前位置之间的距离,7为相同内容的长度。
(30, 11)中,30为相同内容块与当前位置之间的距离,11为相同内容的长度。
由于(两者之间的距离,相同内容的长度)这一对信息的大小,小于被替换内容的大小,所以文件得到了压缩。
a-2)Huffman编码
我们把文件中一定位长的值看作是符号,比如把8位长的256种值,也就是字节的256种值看作是符号。我们根据这些符号在文件中出现的频率,对这些符号重新编码。对于出现次数非常多的,我们用较少的位来表示,对于出现次数非常少的,我们用较多的位来表示。这样一来,文件的一些部分位数变少了,一些部分位数变多了,由于变小的部分变大的部分多,所以整个文件的大小还是会减小,所以文件得到了压缩。
3)deflate压缩算法
DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。
它最初是由Phil Katz为他的PKZIP归档工具第二版所定义的,后来定义在RFC 1951规范中。
人们普遍认为DEFLATE不受任何专利所制约,并且在LZW(GIF文件格式使用)相关的专利失效之前,这种格式除了在ZIP文件格式中得到应用之外也在gzip压缩文件以及PNG图像文件中得到了应用。
DEFLATE压缩与解压的源代码可以在自由、通用的压缩库zlib上找到。
更高压缩率的DEFLATE是7-zip所实现的。AdvanceCOMP也使用这种实现,它可以对gzip、PNG、MNG以及ZIP文件进行压缩从而得到比zlib更小的文件大小。在Ken Silverman的KZIP与PNGOUT中使用了一种更加高效同时要求更多用户输入的DEFLATE程序。
deflate是一种压缩算法,是huffman编码的一种加强。
deflate与gzip解压的代码几乎相同,可以合成一块代码。
三、gzip与deflate区别
deflate使用inflateInit(),而gzip使用inflateInit2()进行初始化,比inflateInit()多一个参数:-MAX_WBITS,表示处理raw deflate数据。因为gzip数据中的zlib压缩数据块没有zlib header的两个字节。使用inflateInit2时要求zlib库忽略zlib header。在zlib手册中要求windowBits为8..15,但是实际上其它范围的数据有特殊作用,见zlib.h中的注释,如负数表示raw deflate。
deflate是最基础的算法,gzip在deflate的raw data前增加了10个字节的gzheader,尾部添加了8个字节的校验字节(可选crc32和adler32)和长度标识字节。