google protobuf_通过protobuf自带gzip压缩对报文进行二次压缩

本文在Windows平台上,详细介绍了如何编译zlib和protobuf,以及如何使用protobuf自带的gzip压缩功能进行数据二次压缩。通过示例展示了client和server如何收发压缩后的protobuf消息,并探讨了数据压缩的效果,指出数据量越大,压缩效果越显著。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

全部在windows平台进行测试

一、编译zlib

从github上下载最新zlib代码,根据教程进行编译,是cmake工程很简单。编译安装好,找到安装目录的include、lib、bin。默认是路径:C:Program Files (x86)zlib

bc95672b622574bfada56a12f68631a8.png

二、编译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." << std::endl;

return -1;

}

gzipOutputStream.Close();//非常重要,如果不关闭,输出流sendbuf里是没有数据的

//end:二次压缩测试

send(sendbuf.data(),sendbuf.size());

六、客户端处理

1)随便发一段数据给服务端

2)onData函数收到服务端应答的protobuf格式数据

3)对收到的数据处理

proto::Person p2;

LOGI("收到数据长度:" << size);

//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("获取协议内容:id=%d,name=%s,number=%s", p2.id(), p2.name().c_str(), p2.phones(0).number().c_str());

七、总结

通过测试发现服务端protobuf数据在60字节以内的时候,经过protobuf自带的gzip压缩之后,数据大小会大于60字节。也就是说数据越压缩越大。

当protobuf数据流大于60字节时,通过protobuf自带的gzip压缩之后体积会变小,数据越大,经过压缩率越明显。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值