自学内容网 自学内容网

C/C++编程-理论学习-通信协议理论

protobuf

简述

作用:
1. 将结构化数据 序列化 进行信息通信、存储。意为,数据结构化管理;意为,对结构化的数据进行序列化,便于发送、存储。可类比XML、JSON。

弊端:
1. buffer占用额外空间,传输比透传降低很多。(这里有一个故事,我们领导极力让单片机和上位机通信,采用protobuf传输数据,端口为串口。我问有何好处,不采用透传自定义协议的原因?他回答protobuf传输效率更高,比如连续8个字节都是0x00,它会智能简化、压缩传输,比如传输0x00,还附带额外信息表明共有8个连续此字节信息。后来事实证明串口透传效率更高,如果透传花费2ms的话,protobuf装填message,序列化,然后将绑定buf传输出去,总共约需要将近20ms,大约差10倍的效率),其实道理也很简单,自定义的透传协议本质不需要序列化,已经是二进制的数据序列了,只要根据格式直接传输、解析即可,效率自然极高。

使用简介

《Nanopb:Basic concenpts》

contents :

  • Proto 文件
    • 编译文件
    • 修改生成行为
    • 输出流
    • 输入流
  • 数据类型
    proto 描述 和 生成的数据结构
  • Field callbacks
    • 编码回调
    • 解码回调
    • 功能名字绑定回调
  • 信息描述
  • Oneof
  • Extension fields
  • Default values
  • Message framing
  • Return values and error handling
  • Static assertions

proto 文件

为了nanopb 编译.proto文件
修改生成器行为

写一个和.proto同名的 .options文件。使用生成器选项文件,可以设置字段的最大大小,进而静态申请其内存。

# Foo.proto
message Foo {
   required string name = 1;
}

# Foo.options
Foo.name max_size:16

streams

回调的通用准则:

  1. IO有错误,编码和解码进程立即终止
  2. 用 ”state“ 存储自己的数据,例如文件描述符
  3. 通过pb_write 和 pb_read 更新 bytes_written 和 bytes_left
  4. 回调也可用于次数据流,,结构内值和初始流近似
  5. 总是读取或写入所请求的完整长度的数据
output streams
struct _pb_ostream_t
{
   bool (*callback)(pb_ostream_t *stream, const uint8_t *buf, size_t count);
   void *state;
   size_t max_size;
   size_t bytes_written;
};

如果callback是空,则只简单的数bytes_written进行发送,并且max_size会被忽略。
否则,bytes_written(要写的数据)+ 已经被写的数据 比 max_size 大, pb_write 会在做任何事之前,返回错误。 如果你不想限制流的大小,注销掉SIZE_MAX即可。

/* example1 */
Person myperson = ...;
pb_ostream_t sizestream = {0};
pb_encode(&sizestream, Person_fields, &myperson);
printf("Encoded size is %d\n", sizestream.bytes_written);

/* example2 */
bool callback(pb_ostream_t `stream, const uint8_t `buf, size_t count)
{
   FILE *file = (FILE*) stream->state;
   return fwrite(buf, 1, count, file) == count;
}

pb_ostream_t stdoutstream = {&callback, stdout, SIZE_MAX, 0};
input streams

不需要知道消息长度。读取时获得EOF错误,将bytes_left设置为0,并返回false。pb_decode会检测到,并且如果EOF出现在恰当位置,会返回ture。

struct _pb_istream_t
{
   bool (*callback)(pb_istream_t *stream, uint8_t *buf, size_t count);
   void *state;
   size_t bytes_left;
};

callback 必须赋值函数指针。bytes_left是将要读取的字节数的上限。如果回调函数像上面描述的那样处理EOF,则可以使用SIZE_MAX。

bool callback(pb_istream_t *stream, uint8_t *buf, size_t count)
{
   FILE *file = (FILE*)stream->state;
   bool status;

   if (buf == NULL)
   {
       while (count-- && fgetc(file) != EOF);
       return count == 0;
   }

   status = (fread(buf, 1, count, file) == count);

   if (feof(file))
       stream->bytes_left = 0;

   return status;
}

pb_istream_t stdinstream = {&callback, stdin, SIZE_MAX};

数据类型


原文地址:https://blog.csdn.net/qq_18661919/article/details/136509115

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!