项目中有很多自定义结构体类型的数据需要保存,然后上位机在读取解析用。写了一堆自定义协议的序列化与反序列化代码,又臭又长,而且序列化的协议是 word 文档,也就是协议跟代码是分家的,既然都分家了,那么不一致就不稀奇了。
那么怎么解决这个问题呢,如果 word 协议可以被编解码程序识别那就完美了。protobuf-c 可以正好可以解决这个问题,当然 protobuf-c 还能解决客户端/服务器通信的问题。
1. 安装
- 安装 protobuf
git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git submodule update --init --recursive
./autogen.sh
./configure
make
make check # make check 失败的话没关系,继续下面的安装
sudo make install
sudo ldconfig
安装不成功的话,检查依赖sudo apt-get install autoconf automake libtool curl make g++ unzip
- 安装 protobuf-c
git clone https://github.com/protobuf-c/protobuf-c.git
./autogen.sh && ./configure && make && make install
2. protobuf-c 生成协议代码
- 编辑 student.proto 文件
syntax = "proto3";
message Student {
required int32 id = 1;
required string name = 2;
required int32 socre = 3;
}
- 生成源文件
protoc --c_out=. student.proto
生成.c和.h文件 student.pb-c.c student.pb-c.h
3. 编写代码
- 编写 student.c 文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "student.pb-c.h"
#define NAME_LEN 32
int main() {
Student stu = STUDENT__INIT; // 初始化
void *buf = NULL;
unsigned int len;
Student *msg = NULL;
stu.name = (char*)malloc(NAME_LEN);
stu.name = "test";
len = student__get_packed_size(&stu); // 算出大小
printf("size of Student info : %u\n", len);
buf = malloc(len);
student__pack(&stu, buf); // 打包
msg = student__unpack(NULL, len, buf); // 解包
printf("msg name : %s\n", msg->name);
student__free_unpacked(msg, NULL); // 释放空间
free(buf);
return 0;
}
- 编译 student.c
gcc student.c student.pb-c.c -o student -lprotobuf-c
注意要链接 protobuf-c 库。
4. 存文件
其实现在存文件还是有问题,没有分隔符。那么解析端无法分隔每条消息。所以还要套一个头标识和长度。比如下面这样:
+------+------+-------+
| flag | size | data |
+------+------+-------+
| header |
5. 在多思考一下
其实也可以不需要用 protoc 工具提前生成代码,只要有一个解析器,在程序运行的时候解析 protoc 协议文件就好了。