protobuf简介

来源:互联网 发布:网络俗语hp是什么意思 编辑:程序博客网 时间:2024/05/30 23:28

原文地址:http://blog.sina.com.cn/s/blog_559f6ffc0101bo7u.html


protobuf简介
~~~~~~~~~~~~
1. protobuf是什么?
protobuf是google出的一个结构化信息传递的工具,用于传递自定的strcut xxx {}内容。
可用于在一个机器上的进程间,两台设备各自的进程间,等等。

2. protobuf如何用?
利用protobuf会生成protobuf编码器和protobuf解码器,两者都依赖protobuf库。
a. 使用proto语言写strcut脚本,一般名称为xxx.proto
b. 用protobuf工具编译脚本生成.c和.h两个文件
c. 使用提供函数
XXX__get_packed_size()获取msg的size
XXX__pack()将msg编码
《== msg发送 ==》   msg发送端
--------------------------------------------------
《== msg接收 ==》   msg接收端
XXX__unpack()将收到的msg解码
XXX__free_unpacked()释放msg资源

3. 例子
下面是基于protobuf然后采用socket通信的程序。
message GenCmd
{
required uint32 cmd = 1;
}

message RetVal
{
required uint32 cmd = 1;
required string cmd_str = 2;
required sint32 ret = 3;
}
通过编译protoc-c --c_out=. fct.proto
生成fct.pb-c.h和fct.pb-c.c
内容略
#include
#include
#include
#include
#include
#include

#include "fct.pb-c.h"

#define FCT_PORT 0x8888
#define MAX_MSG_SIZE 1024


int main(int argc, char * argv[])
{
GenCmd msg = GEN_CMD__INIT; // AMessage
RetVal * ret_msg;
int socket_client;
int recbytes;
int sin_size;
int len;
char buffer[MAX_MSG_SIZE] = {0};
int addr_len = sizeof(struct sockaddr_in);
struct sockaddr_in s_add;

socket_client = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == socket_client)
{
printf("socket fail ! \r\n");
return -1;
}
//printf("socket ok !\r\n");

bzero(&s_add, sizeof(struct sockaddr_in));
s_add.sin_family = AF_INET;
s_add.sin_addr.s_addr = inet_addr("127.0.0.1");
s_add.sin_port = htons(FCT_PORT);
//printf("s_addr = %#x ,port : %#x\r\n", s_add.sin_addr.s_addr, s_add.sin_port);

while (1)
{
printf("input cmd: ");
scanf("%s", buffer);
while (msg.cmd > 0xfffff)
{
scanf("%s", &msg.cmd);
printf("input = %x\n", msg.cmd);
sleep(1);
}
msg.cmd = 0xC2E00000 | msg.cmd;

len = gen_cmd__get_packed_size(&msg);

bzero(buffer, sizeof(buffer));
gen_cmd__pack(&msg, buffer);
//fprintf(stderr, "Writing %d serialized bytes\n", len); // See the length of message

sendto(socket_client, buffer, MAX_MSG_SIZE, 0, (struct sockaddr *)(&s_add), sizeof(struct sockaddr));
recbytes = recvfrom(socket_client, buffer, MAX_MSG_SIZE, 0, (struct sockaddr *)(&s_add), &addr_len);
//printf("client recbytes = %x\n", recbytes);
if (recbytes > 0)
{
//printf("client recbytes = %s\n", buffer);
ret_msg = ret_val__unpack(NULL, recbytes, buffer);
if (ret_msg == NULL)
{
fprintf(stderr, "error unpacking incoming message\n");
exit(1);
}

// display the message's fields.
printf("client Received: cmd %X, str %s, srtr len %d, ret %d\n", ret_msg->cmd, ret_msg->cmd_str, strlen(ret_msg->cmd_str), ret_msg->ret); // required field
// Free the unpacked message
ret_val__free_unpacked(ret_msg, NULL);
}
}

close(socket_client);

return 0;
}

#include
#include
#include
#include
#include
#include
#include

#include "fct.pb-c.h"

#define MAX_MSG_SIZE 1024
#define FCT_PORT 0x8888

typedef enum{
help_cmd = 0,
lspci_cmd,
last_cmd
} command_number;


int check_msg_cmd(unsigned int msg_cmd);
int help_func(void);
int lspci_func(void);

int socket_host;
struct sockaddr_in s_add;


typedef struct {
command_number cmd_number;
char desc[1024];
int (* cmd_func)();
} fct_cmd_t;

fct_cmd_t fct_cmd_array[] = {
{help_cmd, "help cmd", &help_func},
{lspci_cmd, "run shell command - lspci", lspci_func},
{last_cmd, "the last one command", NULL},
};


int check_msg_cmd(unsigned int msg_cmd)
{
unsigned int cmd_array_size;
unsigned int msg_head;
unsigned int msg_num;

cmd_array_size = sizeof(fct_cmd_array)/sizeof(fct_cmd_t);
msg_head = msg_cmd >> 20;
msg_num = msg_cmd & 0xfffff;


if (msg_head == 0xC2E)
{
if ((msg_num < cmd_array_size) && (fct_cmd_array[msg_num].cmd_number == msg_num) && (fct_cmd_array[msg_num].cmd_func != NULL))
{
return 0;
}
}
else
{
return -2;
}

return -1;
}

int help_func(void)
{
int i;
int rc = 0;

for (i = 0;; i++)
{
if (fct_cmd_array[i].cmd_number != last_cmd)
{
printf("X:\t%s\n", fct_cmd_array[i].cmd_number, fct_cmd_array[i].desc);
}
else
goto finish;
}

finish:
return rc;
}

int lspci_func(void)
{
int rc = 0;
rc = system("lspci");
return (rc>>8) & 0xff;
}


int main(int argc, const char * argv[])
{
GenCmd * msg;
RetVal ret_msg = RET_VAL__INIT;
struct sockaddr_in local_addr;
uint8_t receive_buf[MAX_MSG_SIZE];
size_t msg_len;

socket_host = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_host < 0)
{
printf("Shell socket %d failed", FCT_PORT);
return;
}

local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
local_addr.sin_port = htons(FCT_PORT);

if (bind(socket_host, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0)
{
printf("Shell socket bind failed");
close(socket_host);
return;
}

if( eMpmnx_Ninja != GetMfaAssemblyType() ){
printf("Error: It is not RMX1800 product\n");
return -1;
}

if( MS_MFA_MPMNX != GetMfaBoardType() ){
printf("Error: It is not a Meridian_II Card\n");
return -2;
}

InitHardware();
InitMfaLowDispatcher();
InitDspPostResults();
LoadDsp();

while (1)
{
struct sockaddr_in raddr;
socklen_t addrsize;
int readsize;
int receive_size;
unsigned int msg_cmd;
unsigned int msg_head;
unsigned int msg_num;
int cmd_ret_val = 0;

memset(receive_buf, 0, sizeof(receive_buf));
addrsize = sizeof(raddr);
readsize = recvfrom(socket_host, receive_buf, sizeof(receive_buf), 0, (struct sockaddr *)&raddr, &addrsize);
if (readsize > 0)
{
receive_buf[readsize] = '\0';
//printf("received %x\n", readsize);

// Unpack the message using protobuf-c.
msg = gen_cmd__unpack(NULL, readsize, receive_buf);
if (msg == NULL)
{
fprintf(stderr, "error unpacking incoming message\n");
exit(1);
}
// display the message's fields.
//printf("server Received: %X\n", msg->cmd); // required field

msg_cmd = msg->cmd;
msg_head = 0xE2C00000;
msg_num = msg_cmd & 0xfffff;
if (check_msg_cmd(msg_cmd) == -1)
{
printf("msg cmd error, X\n", msg_cmd);
msg_num = 0x00000;
}
cmd_ret_val = fct_cmd_array[msg_num].cmd_func();

ret_msg.cmd = msg_head | msg_num;
ret_msg.cmd_str = "return";
ret_msg.ret = cmd_ret_val;

memset(receive_buf, 0, sizeof(receive_buf));
readsize = ret_val__get_packed_size(&ret_msg);
ret_val__pack(&ret_msg, receive_buf);

//printf("%s\n", receive_buf);
sendto(socket_host, receive_buf, sizeof(receive_buf), 0, (struct sockaddr *)&raddr, sizeof(raddr));
// Free the unpacked message
gen_cmd__free_unpacked(msg, NULL);
}
}

return 0;
}
编译: gcc -o server server.c fct.pb-c.c -lprotobuf-c
gcc -o client client.c fct.pb-c.c -lprotobuf-c
生成server和client
测试:
./server &
./client