您的位置:首页 > 理论基础 > 计算机网络

如何解决http封包中gzip编码的html

2009-07-16 15:09 232 查看
gzip编码,最早由Jean-loup Gailly和Mark Adler创建,用于UNIX系统的文件压缩。我们在Linux中经常会用到后缀为.gz的文件,它们就是GZIP格式的。现今已经成为Internet 上使用非常普遍的一种数据压缩格式,或者说一种文件格式。HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度。(摘在百度百科)。

废话少说,来进入正题吧。

大家都知道,在默认模式下,http协议中发送的网页的Html代码是经过gzip编码后传送的。那么我们怎么才能回复这段编码后的html呢?

大家可能都知道linux下有一个gzip命令。可以把文件压缩成gzip编码的格式,即*.gz

而对于文件的压缩和解压缩,可以采用zlib库中提供的各种接口来进行操作。但是这里问题来了。关于gzip编码的那些函数都带有gz开头的标示。而这些接口维护了一个名叫gz_stream的结构体。并且是针对文件FILE*操作的。

而我们要解决的问题是,我们把截取的封包中的gzip编码的内容拿出来,放到一个buffer中。那么怎么才能针对这个buffer中的数据应用这些接口呢?

我本来的想法是能不能在这些接口中找到专门对内存中的数据进行解码?

考虑这个问题,我看了这个库的源代码。后来放弃了。至于放弃的原因,可能是我意志力不够,或者不想看那些源代码了。总之,我看了一天,看的我头疼。

后来我就想个办法绕开这一思路,走个弯路。问题豁然开朗。

思路如下:

1. 把获取到的经过编码的数据保存到一个文件中。注意写文件的时候一定要以二进制方式。否则是不能解码的。

2. 应用zlib中的接口,gzopen(),gzread(),gzclose()即可完成解码的任务了。

我把这一过程简单封装起来,在VC2005下经过测试,仅提供参考:

// ~GzipParse.h
#ifndef __GZIPPARSE_H_
#define __GZIPPARSE_H_
/*
* 此类用于解码http协议中gzip编码的html数据数据
* 也可用于其他类似用途
*/
class GzipParse
{
public:
//sCompressedData压缩数据的buffer,
//nLen sCompressedData的长度
GzipParse(char *sCompressedData,int nLen);
~GzipParse();
public:
//调用时,请确保unCompressedData的长度足够长,能够容纳解码后的数据
//sUnCompressedData解码数据的buffer
//nLen sUnCompressedData的长度
char *Decode(char *sUnCompressedData,int nLen);
private:
char *m_sCompressedData;
int m_nLen;
};
#endif // __GZIPPARSE_H_
// ~GzipParse.cpp
#include "GzipParse.h"
#include "zlib.h"
#include <fstream>
#ifdef WIN32
#pragma comment(lib,"zlib.lib")
#endif
using std::ofstream;
using std::ios_base;

GzipParse::GzipParse(char *sCompressedData,int nLen)
{
this->m_sCompressedData = sCompressedData;
this->m_nLen = nLen;
}
GzipParse::~GzipParse()
{
}
char * GzipParse::Decode(char *out,int nOutLen)
{
ofstream fout;
fout.open("html.tmp",ios_base::out | ios_base::trunc | ios_base::binary );
fout.write(m_sCompressedData,m_nLen);
fout.close();

gzFile file = gzopen("html.tmp","rb");
int nLength = gzread(file,out,nOutLen);
gzclose(file);
out[nLength] = '/0';

return out;
}
//~ testGzipParse.cpp
#include "GzipParse.h"
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
char * sUnCompress = new char[100];
char sCompress[] = {0x1f,0x8b,0x08,0x08,0x8c,0x9f,0x5E,0x4A,0x00,0x03,0x67,
0x7a,0x69,0x70,0x2e,0x74,0x78,0x74,0x00,0x33,0x34,0x32,
0x36,0x32,0x31,0x1c,0x25,0x46,0x09,0x9a,0x12,0x5c,0x00,
0xb4,0xe9,0x50,0x7F,0x68,0x02,0x00,0x00};

GzipParse gzip(sCompress,sizeof sCompress);
gzip.Decode(sUnCompress);
cout << sUnCompress << endl;
cin.get();
delete []sUnCompress;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐