三、使用zlib库对收到数据进行解压
使用zlib库:http://www.zlib.net/
此软件编译使用的是zlib 1.2.11版本,步骤如下:
1.源码解压后打开VS的命令行,在命令行中执行源码根目录下的\contrib\masmx86\bld_ml32.bat,x64的在\contrib\masmx64\bld_ml64.bat,执行后会在bat文件所在目录下生成两个obj文件和两个lst文件;
2.将生成的obj文件拷到\contrib\vstudio下对应VS版本目录中,VS2015内部版本号是14,拷到\contrib\vstudio\v14即可然后打开sln解决方案文件按需求编译即可,不同项目的不同编译版本在\contrib\vstudio\v14\x86或\contrib\vstudio\v14\x64下可以看到,我这里只用到了zlib静态连接库的Release版本zlibstat.lib;
3.在项目中导入库文件,包含源码根目录下的zlib.h和zconf.h两个头文件:
#include "zlib-1.2.11\zlib.h"
#include "zlib-1.2.11\zconf.h"
切记在项目->属性->配置属性->C/C++->预处理器->预处理器定义
中添加ZLIB_WINAPI
,否则会编译失败,如果提示模块对于SAFESEH映像是不安全的
,在项目->属性->配置属性->链接器->命令行->其它选项
中添加/SAFESEH:NO
即可。
解压函数:[ref]
// zlib解压Gzip
int httpgzdecompress(Byte *zdata, uLong nzdata,
Byte *data, uLong *ndata)
{
int err = 0;
z_stream d_stream = { 0 }; /* decompression stream */
static char dummy_head[2] =
{
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = zdata;
d_stream.avail_in = 0;
d_stream.next_out = data;
//if (inflateInit2(&d_stream, -MAX_WBITS) != Z_OK) return -1;
if (inflateInit2(&d_stream, 47) != Z_OK) return -1;
while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
if ((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
if (err != Z_OK)
{
if (err == Z_DATA_ERROR)
{
d_stream.next_in = (Bytef*)dummy_head;
d_stream.avail_in = sizeof(dummy_head);
if ((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK)
{
return -1;
}
}
else return -1;
}
}
if (inflateEnd(&d_stream) != Z_OK) return -1;
*ndata = d_stream.total_out;
return 0;
}
解压结果明显是经过Base64编码过的,虽然不清楚Zlib自己有没有解码的实现,但是也懒得找了(其实是中文资料少英文不想找),反正Base64的解码也很简单。
需要提高的地方:
第三方库的编译使用的一些注意事项得总结一下,开发的过程中时常要用到别人的轮子,规避掉容易犯的粗心错误省心省力又可以提高效率。