获取http的gzip内容,并解压 问题已经解决,经验分享以及散分:)

Squallxye 2008-11-06 09:11:50
问题:
入问题,问题答案立即呈现在您眼前!

寻找gzip
获取一个网页数据返回的编码类型是gzip,我该怎么解压缩
HTTP头获取?
如何用vb获取网络上的xml文件,并解析内容
关于GZIP的解码
怎样解gzip的压缩
请问Wininet是否可以进行Gzip的http传输,尤其是post的时候!如果可以如何实现?
关于GZIP格式解压缩HTTP数据包的问题,我使用ZLIB为什么必须先保存文件,内存解压缩出错
无法获取$_SERVER["HTTP_REFERER"]
关于GZIP的问题,高分求解!!
.....
等都是关于gzip解压的
问题:
提取http的gzip内容,并解压。
关键点:
1 提取http数据包的内容,主要是gzip格式的
2 数据包的重组
3 在内存中解压gzip数据

这两个周过来,都是在网上过来的,得到网友的帮助不少,很是感激,为了不让这个问题继续困扰后来的un_gziper,特写此文。
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;
}


后记,这个过程是痛苦的,但也是幸福的!
这里我发起一个小小的倡议,对所有关注gzip解压的问题的网友:
我们都遇到了一个问题就是zlib的文档都是英文的,有个别网友翻译了开头的一小部分,但是这是不够的!
所以,我希望有兴趣的朋友可以一起来帮zlib的文档翻译成为中文!
有兴趣的可以加我!




...全文
6208 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
applelemon_1985 2012-02-14
  • 打赏
  • 举报
回复
楼主伟大
lanrui588 2010-10-09
  • 打赏
  • 举报
回复
http://blog.sina.com.cn/s/blog_65db99840100kwh9.html
这篇文章讲的蛮清楚
jiwt 2010-08-11
  • 打赏
  • 举报
回复
谢谢楼主!!!
yinyuehan823 2010-04-07
  • 打赏
  • 举报
回复
学习了~,感谢LZ
chenhaoxiao 2009-09-15
  • 打赏
  • 举报
回复
ing........
crackly1986 2009-09-09
  • 打赏
  • 举报
回复
居然不能看
youyou0_0 2009-08-20
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 dozec 的回复:]
获取一个网页数据返回的编码类型是gzip,我该怎么解压缩
[/Quote]

头文件是什么?
sheds 2009-04-17
  • 打赏
  • 举报
回复
还能顶吗
zhsunson 2009-03-15
  • 打赏
  • 举报
回复
这段代码如果要转成VB的代码应该如何写?
Squallxye 2009-02-12
  • 打赏
  • 举报
回复
楼上兄弟,看我写的相关的帖子,用zlib库函数即可解压gzip数据
dozec 2009-02-11
  • 打赏
  • 举报
回复
获取一个网页数据返回的编码类型是gzip,我该怎么解压缩
happy灬世纪 2009-01-07
  • 打赏
  • 举报
回复
CHUNK是什么东东?
Squallxye 2008-12-26
  • 打赏
  • 举报
回复
还有个问题:
对chunked类型的数据包,要注意几个地方:
1 得到gzip的头部,为10个字节
2 得到chunked的大小
3 得到chunked的数据部分

其实对应chunked类型的数据,它虽然是分块传输的,但是不一定一个数据包就恰好装了一块‘chunked’的数据,因此得注意
chunked的结构:
\r\n\r\nsize\r\ngzipheader\r\nsize\r\nchunkedData\r\nsize\r\n.......
mengxihe 2008-12-17
  • 打赏
  • 举报
回复
好帖啊,偶今天也遇到这个问题鸟
SZTSKJ 2008-11-09
  • 打赏
  • 举报
回复
Squallxye 2008-11-09
  • 打赏
  • 举报
回复
结贴了,看来得自己翻译zlib的英文说明文档了,一段时间后再上传上来和大家分享,敬请期待...
cceczjxy 2008-11-08
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 Squallxye 的回复:]
文章有遗漏的地方,请各位指出啊,我想把这个弄成一个小专题,一下搞定,以后别再困扰后来的程序员了!
[/Quote]

楼主的'分享'精神值得大家学习.
希望楼主的帖子能继续下去
jufeng2309 2008-11-08
  • 打赏
  • 举报
回复
学习..........文件处理.......
Squallxye 2008-11-08
  • 打赏
  • 举报
回复
文章中提到的http数据结尾的标志应该是:“\r\n\r\n”
rediscovery 2008-11-07
  • 打赏
  • 举报
回复
千金散尽还复来,支持,顶
加载更多回复(6)
第15章 键盘与鼠标 389 15.1 鼠标操作技巧 390 0626 鼠标双击窗体时模拟键盘Tab键操作 390 0627 定义鼠标指针形状 390 0628 自定义鼠标的图片 391 0629 鼠标拖放复制文本 391 0630 如何使用鼠标单击添加控件 392 0631 如何获得鼠标在窗体上的位置 392 0632 如何交换鼠标左右键功能 392 0633 如何隐藏和显示鼠标 393 0634 如何获取光标闪烁的频率 394 0635 如何获得屏幕上鼠标的坐标 394 0636 如何限制鼠标在某一区域工作 394 0637 如何利用鼠标绘图 395 0638 如何获取鼠标双击时间间隔 396 0639 如何获取鼠标键数 396 0640 如何显示鼠标的等待光标 397 0641 如何禁用鼠标左键 397 0642 如何模拟鼠标操作 398 0643 如何实现鼠标穿透窗体 399 0644 如何记录鼠标行为 399 15.2 键盘操作技巧应用 400 0645 如何禁用输入法编辑器 400 0646 如何打开和关闭输入法编辑器 400 0647 回车转换成Tab键 400 0648 如何获取组合键 401 0649 如何获取功能键 401 0650 如何判断NumLock键和CapsLock键是否锁定 401 0651 如何屏蔽 Alt + F4 键关闭窗体 402 0652 如何实现按下 Esc 键关闭窗体 402 0653 如何避免按 Enter 键产生“嘀”声 403 0654 如何设置键盘热键 403 第16章 文件、文件管理及数据流 405 16.1 获取文件基本信息 406 0655 获取文件创建的日期和时间 406 0656 如何检索路径中的文件名和扩展名 406 0657 如何获得文件的大小 407 0658 如何修改文件属性 407 0659 如何监视文件系统变化情况 408 0660 如何获取文件的系统启动方式 408 0661 如何获取文件名禁止使用的字符 409 0662 如何获取路径名禁止使用的字符 410 0663 如何获取指定目录的上级目录 410 16.2 文件基本操作 411 0664 判断文件是否存在 411 0665 创建一个文件用于写入UTF-8编码的文本 411 0666 OpenRead方法打开现有文件并读取 412 0667 打开现有UTF-8编码文本文件并进行读取 412 0668 OpenWrite方法打开现有文件并进行写入 413 0669 如何读取文件中的第一行数据 413 0670 如何向文件中写入数据 413 0671 如何读取文件中所有数据 414 0672 如何创建临时文件 414 0673 如何实现文件替换 415 0674 使用递归法删除文件夹中所有文件 415 0675 如何更改文件扩展名 416 0676 如何实现复制文件 416 0677 如何修改文件名 416 0678 如何删除文件 417 0679 如何上传文件 417 0680 如何下载文件 418 0681 如何拖放文件 419 0682 如何搜索文件 419 16.3 文件夹基本操作 420 0683 如何创建文件夹 420 0684 如何移动文件夹 420 0685 如何修改文件夹名称 421 0686 如何遍历文件夹 421 0687 如何删除文件夹 422 16.4 数据流操作 422 0688 如何读写内存数据流 422 0689 如何创建二进制文件 423 0690 如何读取二进制文件 423 0691 如何使用缓冲流 424 16.5 加密、解密及解压缩文件 425 0692 加密和解密文件 425 0693 如何使用对称算法加密文件 425 0694 如何使用对称算法解密文件 426 0695 如何使用GZip压缩文件 427 0696 如何使用GZip解压文件 428 0697 如何使用WinRAR压缩文件 429 0698 如何使用WinRAR解压文件 429 16.6 其他 430 0699 设置文件的访问模式 430 0700 如何在C#应用程序中使用INI文件 430 0701 如何操作帮助文件 431 0702 如何操作Word文件 432 0703 如何操作Excel文件 433 0704 如何将文本文件转换成网页文件 434 0705 如何产生随机文件夹名或文件名 435 0706 如何将长文件名转换成短文件名 436 0707 如何用程序创建XML文档并写入内容 436 0708 如何通过DataSet对象读取XML文件 438 0709 如何动态创建XML文件节点 439 0710 如何实现XML文件数据类型的转换 439 0711 将图片保存到XML文件中 440 0712 如何比较两个文件的内容是否相同 440 0713 如何以缩略图形式上传图片文件 441 0714 如何解析只有一种格式的文本文件 442 0715 如何解析含有多种格式的文本文件 443 第17章 Windows开发技术 445 17.1 获取计算机系统信息 446 0716 如何获取系统时间 446 0717 如何获取系统目录 446 0718 如何获取计算机名称 446 0719 如何获取当前程序运行目录 446 0720 如何获得操作系统版本号 446 17.2 获取计算机硬件信息 446 0721 如何获取CPU编号 446 0722 如何获取显示设备的PNPDeviceID 447 0723 如何获取声音设备的PNPDeviceID 447 0724 如何获取硬盘编号 447 0725 如何获取CPU的版本信息 448 0726 如何获取CPU的产品名称信息 448 0727 如何获取CPU的制造商名称 448 0728 如何获取主板制造商 449 0729 如何获取主板编号 449 0730 如何获取主板型号 449 0731 如何获取磁盘空间 450 0732 如何获取磁盘剩余空间 450 0733 如何确定屏幕的分辨率 451 0734 如何获得磁盘的卷标 452 0735 如何获得磁盘的文件系统类型 452 17.3 获取特殊文件夹路径 453 0736 如何获取ProgramFiles目录全路径 453 0737 如何获取桌面目录全路径 453 0738 如何获取开始菜单目录全路径 454 0739 如何获取用户程序组目录全路径 454 0740 如何获取文档模板目录全路径 455 0741 如何获取收藏夹目录全路径 455 0742 如何获取共享组件目录全路径 456 0743 如何获取我的图片目录全路径 456 0744 如何获取Internet历史记录全路径 457 0745 如何获取Internet临时文件目录全路径 457 0746 如何设置可用样式 457 17.4 获得Windows当前用户 458 0747 如何获取当前用户 458 0748 如何判断当前用户是否是普通用户 458 0749 如何判断当前用户是否是超级用户 458 0750 如何判断当前用户是否是系统管理员 459 0751 如何判断当前用户是否是系统操作员 459 0752 如何判断当前用户是否是备份操作员 460 0753 如何判断当前用户是否是打印操作员 460 0754 如何判断当前用户是否是复制程序员 461 0755 如何判断当前用户是否是账户操作员 461 17.5 Windows日志 462 0756 如何获取系统日志信息 462 0757 如何获取安全日志信息 462 0758 如何获取应用程序日志信息 463 0759 如何创建并写入自定义日志信息 464 0760 如何向系统日志写入自定义数据 464 0761 如何向应用程序日志写入自定义信息 465 17.6 计算机控制 465 0762 列举系统中所有窗口 465 0763 C#实现键盘钩子 465 0764 如何关闭计算机 466 0765 如何抓屏 466 0766 如何休眠计算机 467 0767 如何禁止使用Windows任务管理器 468 0768 如何为文件新增右键菜单项 468 0769 如何设置系统仅能运行的程序 469 0770 如何获取本地计算机上所有的进程 469 0771 如何启动一个进程 470 0772 怎样杀死一个进程 470 0773 如何获取远程计算机上所有的进程 470 17.7 其他相关技术 470 0774 如何在注册表中保存窗体的大小和位置 470 0775 如何实现程序间注册表内传递变量 471 0776 在使用OpenFileDialog中的相对路径问题 471 0777 如何设置启动时自动执行程序 471 0778 C#编程实现Windows XP风格的界面 471 0779 用C#实现文件查找功能 473 0780 如何序列化对象 473 0781 如何实现特殊形状的窗体 474 0782 如何移动正在使用的文件 474 0783 如何实现类似QQ的程序界面 475 0784 如何实现动画显示窗体 476 0785 如何显示和隐藏任务栏 477 0786 如何实现OutLook界面 478 0787 如何在C#中回车换行 478 0788 如何获取进程的命令行 479 0789 如何按行读取文本并显示行数 479 0790 如何在Form中嵌入Excel 479 0791 如何使用互斥量禁止程序运行两个实例 480 0792 如何使用进程名禁止程序运行两个实例 480 0793 如何获取控制台应用程序的显示结果 481 0794 如何用@代替路径中的转义字符 482

23,131

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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