使用WinINet下载网页,如何处理服务端返回内容为gzip或deflate编码的情况?

zym_123456 2011-03-20 11:26:56
使用WinINet,如何处理服务端返回内容为gzip或deflate编码的情况?

MSDN上面应该证实,在Windows Server 2008 与 Windows Vista之前,WinINet不会自动处理解码,需要应用程序自己处理。

1、能否在客户端Http头添加个什么内容,让服务端返回内容不加压缩编码。测试过HTTP头不加Accept-Encoding,有些网站也会返回gzip或deflate编码,例如:http://www.sohu.com/。这个服务端返回gzip或deflate编码是否服务端强制的?

2、应用程序自己处理的话,怎么处理?做过的帮忙贴一下解决方案相关代码例子,应该很多人在找这个的,解决了功德无量呀!!!!
...全文
538 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
axx1611 2013-02-22
  • 打赏
  • 举报
回复
HTTP协议规定,不写Accept-Encoding则服务端认为客户端可以接受任何类型的编码, 而用Accept-Encoding: identity则服务端才会保证一定发送RAW数据
myy 2011-03-22
  • 打赏
  • 举报
回复
1、能否在客户端Http头添加个什么内容,让服务端返回内容不加压缩编码。测试过HTTP头不加Accept-Encoding,有些网站也会返回gzip或deflate编码,例如:http://www.sohu.com/。这个服务端返回gzip或deflate编码是否服务端强制的?
----------------------------------------------
按理说服务器端也应该遵循规范,像你举的www.sohu.com的例子只能说它没有严格遵循规范或故意为之。

2、应用程序自己处理的话,怎么处理?做过的帮忙贴一下解决方案相关代码例子,应该很多人在找这个的,解决了功德无量呀!!!!
----------------------------------------------
自己处理也不难,gzip解压有现成的zlib库,不过楼上说的“用 Content-Length ”确定长度有时是不行的,
很多服务器不返回 Content-Length 头,而用 chunk 编码格式(可参考:http://blog.csdn.net/gooogledev/archive/2009/03/11/3978850.aspx)
MoXiaoRab 2011-03-21
  • 打赏
  • 举报
回复
抱歉,我题目没看好,原来你是Vista之前的系统啊?

自己解压GZIP关键点:
1 提取http数据包的内容,主要是gzip格式的
2 数据包的重组
3 在内存中解压gzip数据

1 数据包内存的提取:
关键的地方是找到gzip内存的开始位置以及如何确定gzip内容的大小
开始位置:“Content-Encoding: gzip\r\n\r\n”
gzip大小:“Content-Length:”后面的就是了
2 数据包的重组,一般网页的内容很少是一个数据包可以装得下的,所以都得进行gzip之后再用多个数据包进行传输
关键的地方是:
get请求数据包的ack和seq与http返回数据包的ack,seq有密切的联系:
举例说明:
get请求:ack=0,seq=0
http1:seq=0,ack=584
http2: seq=1420,ack=584
...
简单的分析说明可以看出,我们的算法设计:
首先得到get请求的ack,返回的数据包的seq等于这个值,同时记下这个数据包的ack,后面进行分包发送的http的数据包的ack都是这个值,这个是关键点之一,同时综合
Content-Length就可以得到gzip的全部内容。
至此,原始数据提取完毕,该是如何解压的问题了
3解压gzip
我做了上面的1,2步以后将内容保存到文件里面,用gzip命令可以打开,验证了数据的完整性。
而后我采用了zlib提供的uncompress函数,和大多数的网友一样,都是犯了一个致命的错误,没有仔细的阅读zlib的文档!导致一次次无谓的识别!
事实上zlib格式和gzib格式是有差别的,而uncompress是用来解压zlib格式文件的,这就是为什么会出现用compress函数压缩的数据,在内存中可以直接用uncompress函数进行解压的,而就不能解压gzip数据的问题!

后来测试了zlib包里面的example例子,算是对zlib有了一点点的了解,应该用inflate类函数进行解压!
当然这样遇到了问题,格式不对!
后来在网上看到的帖子:gzip格式用inflate函数还不行,必需要用inflateInit2(&strm, 47);



int inflate_read(char *source,int len,char **dest,int gzip)
{
int ret;
unsigned have;
z_stream strm;
unsigned char out[CHUNK];
int totalsize = 0;

/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;

if(gzip)
ret = inflateInit2(&strm, 47);
else
ret = inflateInit(&strm);

if (ret != Z_OK)
return ret;

strm.avail_in = len;
strm.next_in = source;

/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&strm);
return ret;
}
have = CHUNK - strm.avail_out;
totalsize = have;
*dest = realloc(*dest,totalsize);
memcpy(*dest totalsize - have,out,have);
} while (strm.avail_out == 0);

/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
MoXiaoRab 2011-03-21
  • 打赏
  • 举报
回复
看http://msdn.microsoft.com/en-us/library/aa385328(v=vs.85).aspx这里的INTERNET_OPTION_HTTP_DECODING 下面的Content Encoding.
jwybobo2007 2011-03-21
  • 打赏
  • 举报
回复
如果不解码,就去下gzip或者deflate解码库试试
hurryboylqs 2011-03-20
  • 打赏
  • 举报
回复
我记得WinINet会自动解码的,除非是自己用socket api写才不会

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧