第三项 zlib压缩与base64解压
上一项说到,用xml作为数据用于网络传输,承担的开销太大,文本数据比二进制数据的时间与空间效率相对很低,并且很多传输协议对传输的数据大小有限制,再次选择xml就可能无法传说过大的数据。所以在此背景下我们可以对xml进行压缩之后再进行传输。
一、zlib解压缩工具
Zlib是一种用于数据压缩的函数库,由于Zlib压缩效果比LZW好,而且解压缩速度快,使用DEFLATE算法。最初是为libpng函数库开发,后来普遍为许多软件所使用。zlib为自由软件。
在zlib官网上下载源码编译后生成库文件,并导入头文件就可以直接调用其接口,开始使用,具体可以自行搜索教程。
我在使用zlib用于项目中时只是用到了少部分几个接口。
压缩:
int CMyZlib::MyCompressStr( const char* pchSrcXML, int dwSrcLen, char* pchDstMsg, int& dwDstLen )
{
int dwOutLen = compressBound(dwSrcLen+1);
///zlib压缩
char achOutBuf[102400] = {0};
int ret = compress((Bytef *)achOutBuf, (uLongf *)&dwOutLen, (Bytef *)(pchSrcXML), (uLong)dwSrcLen);
if ( ret != Z_OK)
{
memcpy(pchDstMsg, achOutBuf, dwOutLen);
dwDstLen = dwOutLen;
}
return ret;
}
解压:
int CMyZlib::MyUnCompressStr( const char* pchSrcXML, int dwSrcLen, char* pchDstMsg, int& dwDstLen )
{
char achOutBuf[102400] = {0};
uLongf dwOutLen = 102400;
int ret = uncompress( (Bytef *)achOutBuf, &dwOutLen, (Bytef *)pchSrcXML, (uLong)dwSrcLen);
if ( ret != Z_OK)
{
memcpy(pchDstMsg, achOutBuf, dwOutLen);
dwDstLen = dwOutLen;
}
return ret;
}
为了在工作应用中可以更好的调试问题,我自己使用的了gzopen、gzread、gzwrite接口,编写了小型mfc界面,用于自动解析抓包中被压缩的数据,可以一目了然。
但是同时出现了一个问题:有的时候我们需要先解析xml的根标签来判断这个是什么样的消息然后再处理,所以不能将整个xml直接压缩,考虑可以将xml中子标签的内容进行压缩,但是zlib压缩后的数据是二进制数据不能直接塞入标签,最后考虑在压缩的基础上再进行base64编码。
二、base64编码
Base64是最常用的编码之一,Base64编码在RFC2045中定义,它被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。
base64原理:
A、按字符串长度,以每3个8bit的字符为一组。
B、获取每个字符的ASCII编码,将ASCII编码转换成8bit的二进制,得到一组3*8=24bit的字节。
C、将这24bit划分为4个6bit的字节,并在每个6bit的字节前面都填两个高位0,得到4个8bit的字节。
D、将这4个8bit的字节转换成10进制,对照Base64编码表得到对应编码后的字符。
E、如果被编码字符长度不是3的倍数的时候,则都用0代替,对应的输出字符为=。
改良上一文章的工具,将base64结合进去。