protobuf介绍以及使用方法用例



概述

protobuf作为网络通信时的消息载体,不仅效率高,而且还加快开发进度,减少了BUG

但是protobuf消息生成的类,不管是C++\Java还是其他第三方支持的语言C等生成的消息类,都不太适合用于业务逻辑处理(没有100%的不行,如果非要使用message类作为业务逻辑对象,那么耦合性就太高了)。因此很多时候,我们都需要重复定义至少一份业务逻辑对象,至少是客户端和服务器各一份。那么就涉及到业务逻辑对象和protobuf message之间的互相复制的问题。

1.1 Protobuf使用说明

一个简单的amessage.proto文件如下所示:

message  AMessage
{
    required int32 a=1; 
    optional int32 b=2; 
    
     oneof test_oneof {    
         string c=3;    
         int32  d=4;    
     }    
}


使用如下命令在当前目录下生成protobuf.c文件和.h文件:

protoc-c --c_out=. amessage.proto

序列化AMessage的代码amessage_serialize.c如下所示:

#include <stdio.h>
#include <stdlib.h>
#include "amessage.pb-c.h"

int main (int argc, const char * argv[]) 
{
    AMessage msg = AMESSAGE__INIT;    // AMessage
    void *buf;                        // Buffer to store serialized data
    unsigned len;                     // Length of serialized data
    char *word = "hello world!";
    
    if (argc != 2 && argc != 3)
    {    // Allow one or two integers
        fprintf(stderr,"usage: amessage a [b]\n");
        return 1;
    }
    
    msg.a = atoi(argv[1]);
    if (argc == 3)    { msg.has_b = 1; msg.b = atoi(argv[2]); }
    msg.c = word;
    msg.test_oneof_case = AMESSAGE__TEST_ONEOF_C;
    
    len = amessage__get_packed_size(&msg);
    
    buf = malloc(len);
    amessage__pack(&msg,buf);
    
    fprintf(stderr,"Writing %d serialized bytes\n",len);  // See the length of message
    fwrite(buf,len,1,stdout);  // Write to stdout to allow direct command line piping
    
    free(buf);    // Free the allocated serialized buffer
    return 0;
}

注意事项:

使用A_MESSAGE__INIT宏来初始化消息结构体

成员has_b表示可选成员b是否存在

l 成员test_oneof_case指示oneof使用的成员是哪一个

l AMESSAGE__TEST_ONEOF_C宏表示oneof使用的成员是c

l amessage__get_packed_size函数返回序列化后消息的长度

l amessage__pack函数序列化消息

反序列化消息的代码amessage_deserialize.c如下所示:

#include <stdio.h>
#include <stdlib.h>
#include "amessage.pb-c.h"
#define MAX_MSG_SIZE 1024

static size_t
read_buffer (unsigned max_length, uint8_t *out)
{
    size_t cur_len = 0;
    size_t nread;
    while ((nread = fread(out + cur_len, 1, max_length - cur_len, stdin)) != 0)
    {
        cur_len += nread;
        if (cur_len == max_length)
        {
            fprintf(stderr, "max message length exceeded\n");
            exit(1);
         }
    }
    return cur_len;
}

int main (int argc, const char * argv[]) 
{
    AMessage *msg;

    // Read packed message from standard-input.
    uint8_t buf[MAX_MSG_SIZE];
    size_t msg_len = read_buffer (MAX_MSG_SIZE, buf);

    // Unpack the message using protobuf-c.
    msg = amessage__unpack(NULL, msg_len, buf);    
    if (msg == NULL)
    {
        fprintf(stderr, "error unpacking incoming message\n");
        exit(1);
    }

    // display the message's fields.
    printf("Received: a=%d",msg->a);       // required field
    if (msg->has_b)                        // handle optional field
        printf("  b=%d",msg->b);
    if (msg->test_oneof_case == AMESSAGE__TEST_ONEOF_C)                   
        printf("  c=%s",msg->c);
    else if (msg->test_oneof_case == AMESSAGE__TEST_ONEOF_D)
        printf("  d=%d",msg->d);

    printf("\n");

    // Free the unpacked message
    amessage__free_unpacked(msg, NULL);
    return 0;
}


通过命令gcc amessage_serialize.c amessage.pb-c.c -o amessage_serialize -I/usr/local/include  -I. -L/usr/local/lib -lprotobuf-cgcc amessage_deserialize.c amessage.pb-c.c -o amessage_deserialize -I/usr/local/include -I. -L/usr/local/lib -lprotobuf-c编译以上代码。

在命令行输入下列命令查看结果

./amessage_serialize 10 2 | ./amessage_deserialize
Writing: 18 serialized bytes
Received: a=10  b=2  c=hello world!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十年23

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值