全部在windows平台进行测试
一、编译zlib
从github上下载最新zlib代码,根据教程进行编译,是cmake工程很简单。编译安装好,找到安装目录的include、lib、bin。默认是路径:C:Program Files (x86)zlib
二、编译protobuf
编译过程很简单,这里就不详细介绍了。只说重点:
1)在使用cmakeUI界面编译的时候注意选择x64模式,默认是生成静态库,以下也以静态库为基础进行配置。
2)在使用cmake生成vs工程文件之后,在vs的libprotobuf工程属性里增加宏:HAVE_ZLIB
3)在vs的protobuf工程属性里增加zip的头文件路径。(静态库所以不需要配置链接zlib)
三、用c++写一个简单的client、server工程用于测试收发数据
(这里不用文件的形式测试,太符合实际使用场景)
并写一个简单的IDL文件test.proto,使用前面编译protobuf生成的protoc.exe文件生成新的接口代码文件。
protoc.exe --cpp_out=./ test.proto #注意中间有两处空格
将生成的接口文件引用到client和server工程里。
示例:test.proto
syntax = "proto3";
package proto;
message Person{
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
}
四、client和server工程的收到数据的接口定义
int onData(char* data, int size)
五、server端处理逻辑
(我这里是服务端构造数据发给客户端)
1)接收客户端的数据请求。
2)收到请求后对请求数据不做处理,直接构造应答protobuf报文
3)onData中构造应答protobuf报文示例
std::string out;
proto::Person p;
proto::Person::PhoneNumber* iphone;
p.set_id(1);
p.set_name("Desi5555555555555555");
iphone = p.add_phones();
iphone->set_number("123456");
iphone->set_type(proto::Person_PhoneType::Person_PhoneType_HOME);
iphone = p.add_phones();
iphone->set_number("888888");
iphone->set_type(proto::Person_PhoneType::Person_PhoneType_WORK);
p.set_email("999@dd.com");
//begin:二次压缩测试
std::string sendbuf;
google::protobuf::io::StringOutputStream outputFileStream(&sendbuf);
google::protobuf::io::GzipOutputStream::Options options;
options.format = google::protobuf::io::GzipOutputStream::GZIP;
options.compression_level = _COMPRESSION_LEVEL;
google::protobuf::io::GzipOutputStream gzipOutputStream(&outputFileStream, options);
if (!p.SerializeToZeroCopyStream(&gzipOutputStream))
{
std::cerr <<"Failed to write scene." <endl;
return -1;
}
gzipOutputStream.Close();//非常重要&#xff0c;如果不关闭&#xff0c;输出流sendbuf里是没有数据的
//end:二次压缩测试
send(sendbuf.data(),sendbuf.size());
六、客户端处理
1)随便发一段数据给服务端
2)onData函数收到服务端应答的protobuf格式数据
3)对收到的数据处理
proto::Person p2;
LOGI("收到数据长度:" < //begin:解压被压缩的数据
std::string recvbuf(data,size);
google::protobuf::io::ArrayInputStream input(recvbuf.data(), recvbuf.size());
google::protobuf::io::GzipInputStream gzip(&input, google::protobuf::io::GzipInputStream::GZIP);
if (!p2.ParseFromZeroCopyStream(&gzip))
{
LOGI("解析失败");
return false;
}
//end:解压被压缩的数据
LOGFMTI("获取协议内容&#xff1a;id&#61;%d,name&#61;%s,number&#61;%s", p2.id(), p2.name().c_str(), p2.phones(0).number().c_str());
七、总结
通过测试发现服务端protobuf数据在60字节以内的时候&#xff0c;经过protobuf自带的gzip压缩之后&#xff0c;数据大小会大于60字节。也就是说数据越压缩越大。
当protobuf数据流大于60字节时&#xff0c;通过protobuf自带的gzip压缩之后体积会变小&#xff0c;数据越大&#xff0c;经过压缩率越明显。