Protocol Buffer使用

字数2630 阅读5067 评论1 喜欢12

我们种蒙行使protocol
buffer来进展服务器和客户端的信交互,服务器使用C++,所以本文主要讲述protocol
buffer C++方面的使用,其他语言方面的应用参见google的官文档.

1.概览

1.1 什么是protocol buffer

protocol
buffer是google的一个开源项目,它是用来结构化数据出错行化的灵巧、高效、自动的措施,例如XML,不过她比xml更有些、更快、也还简明。你不过
以定义自己之数据结构,然后用代码生成器生成的代码来读写这数据结构。你甚至足以于无需重新部署程序的事态下更新数据结构。

2.使用

2.1概念一个音类型

message SearchRequest 
{
  required string query = 1;
  optional int32 page_number = 2;// Which page number do we want?
  optional int32 result_per_page = 3;// Number of results to return per page.
}

欠消息定义了三独字段,两个int32色及一个string类型的字段,每个字段由字段限制,字段类型,字段名和Tag四片组成.对于C++,每一个.proto文本通过编译之后都见面相应的变化一个.h和一个.cc文件.

字段限制

字段限制共有3类:
required:必须赋值的字段
optional:可有可无的字段
repeated:可再次字段(变长字段),类似于数值
由一些史由来,repeated字段并从未设想着那高效,新本子被允许下特别之选项项来得到更快速的编码:

repeated int32 samples = 4 [packed=true];

Tags

消息受到之各一个字段都起一个独一无二的数值类的Tag.1到15下一个字节编码,16顶2047采取2单字节编码,所以应以Tags
1到15雁过拔毛频繁利用的许段.
好指定的绝小之Tag为$$1$$,最可怜啊$$2^{29}-1$$或$$536,870,911$$.但是休可知应用$$19000$$到$$19999$$之间的价值,这些价值是养给protocol
buffer的.

注释

使用C/C++的//语法来补偿加字段注释.

2.2 值类型

proto的值类型与实际语言中值类型的对应关系.

2.3 可选取字段及缺少省值

每当信分析时,如果发现消息中从未含可选取字段,此时见面拿信息分析对象中互呼应的字段设置为默认值,可以由此下面的语法为optional字段设置默认值:

optional int32 result_per_page = 3 [default = 10];

设若没点名默认值,则会采用系统默认值,对于string默认值为空字符串,对于bool默认值为false,对于数值类型默认值为0,对于enum默认值为定义着的第一个元素.

2.4 枚举

message SearchRequest 
{
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3 [default = 10];
  enum Corpus 
  {
    UNIVERSAL = 0;
    WEB = 1;
    IMAGES = 2;
    LOCAL = 3;
    NEWS = 4;
    PRODUCTS = 5;
    VIDEO = 6;
  }
  optional Corpus corpus = 4 [default = UNIVERSAL];
}

出于枚举值采用varint编码,所以为了提高效率,不建议枚举值取负数.这些枚举值可以在其他信息定义着重复使用.

2.5 使用另外消息类型

可采用一个信之定义作为其它一个音的字段类型.

message Result 
{
  required string url = 1;
  optional string title = 2;
  repeated string snippets = 3;
}

message SearchResponse 
{
  repeated Result result = 1;
}

可以行使import语法来含有另外一个.proto文件.

import "myproject/other_protos.proto";

2.6 嵌套类型

当protocol中好定义如下的嵌套类型

message SearchResponse 
{
  message Result 
  {
    required string url = 1;
    optional string title = 2;
    repeated string snippets = 3;
  }
  repeated Result result = 1;
}

使在另外一个音讯备受需要采用Result概念,则可经过Parent.Type来使用.

message SomeOtherMessage 
{
  optional SearchResponse.Result result = 1;
}

protocol支持再次甚层次之嵌套和分组嵌套,但是以组织清晰起见,不建议用了好层次的嵌套,建议通过
2.5 小节提到的办法来实现.

2.7 更新一个数据类型

每当创新一个数据类型时更多的凡索要考虑与旧本子的兼容性问题:

  1. 并非转移任何已是字段的Tag值,如果改变Tag值可能会见造成数值类不匹配,具体原因到protocol编码
  2. 建议使用optionalrepeated字段限制,尽可能的削减required的使用.
  3. 未需之字段可以去,删除字段的Tag不应该当新的音讯定义着使用.
  4. 切莫需要的字段可以变为扩充,反之亦然只要项目及数值还保存
  5. int32, uint32, int64, uint64,
    bool凡是相匹配的,这表示可以用中间同样种档次任意改编为另外一栽类型而休会见时有发生其他问题
  6. sint32sint64凡是互相匹配的
  7. stringbytes凡相互配合的
  8. fixed32 兼容 sfixed32, fixed64 兼容 sfixed64.
  9. optional 兼容repeated

2.8 扩展

extend特性来让您声明一些Tags值来供第三正扩大使用.

message Foo 
{
  // ...
  extensions 100 to 199;
}

倘若你于你的proto文件被定义了上述信息,之后人家当外的.proto文件中import你的.proto文件,就好应用你指定的Tag范围的值.

extend Foo 
{
  optional int32 bar = 126;
}

于访问extend中定义之字段和,使用的接口和一般定义之发出接触未平等,例如set方法:

    Foo foo;
    foo.SetExtension(bar, 15);

接近之起HasExtension(), ClearExtension(), GetExtension(), MutableExtension(), and AddExtension()等接口.

2.9 选项

  • optimize_for (file option): 可以装的值有SPEED, CODE_SIZE,
    LITE_RUNTIME. 不同之选项会坐下述方式影响C++, Java代码的生成.T

    • SPEED (default): protocol
      buffer编译器将会见转序列化,语法分析和其它便捷操作信息类型的方式.这吗是参天的优化增选项.确定是转的代码比较大.
    • CODE_SIZE: protocol
      buffer编译器将会晤变卦绝小之近乎,确定是比SPEED运行而缓慢
    • LITE_RUNTIME: protocol buffer编译器将会晤生成只依靠”lite” runtime
      library (libprotobuf-lite instead of libprotobuf)的类.
      lite运行时库比总体库更小而去了如descriptors 和
      reflection等特征. 这个选项通常用于手机平台的优化.

option optimize_for = CODE_SIZE;

3.常用API介绍

对如下信定义:

// test.proto
message PBStudent 
{    
    optional uint32 StudentID   = 1;
    optional string Name        = 2;
    optional uint32 Score       = 3;
}    

message PBMathScore
{    
    optional uint32 ClassID     = 1;  
    repeated PBStudent ScoreInf   = 2;
}

protocol
buffer编译器会为每个消息生成一个像样,每个接近富含基本函数,消息实现,嵌套类型,访问器等部分.

3.1 基本函数

public:
 PBStudent();
 virtual ~PBStudent();

 PBStudent(const PBStudent& from);

 inline PBStudent& operator=(const PBStudent& from) {
   CopyFrom(from);
   return *this;
 }

 inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
   return _unknown_fields_;
 }

 inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
   return &_unknown_fields_;
 }

 static const ::google::protobuf::Descriptor* descriptor();
 static const PBStudent& default_instance();

 void Swap(PBStudent* other);

3.2 消息实现

PBStudent* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const PBStudent& from);
void MergeFrom(const PBStudent& from);
void Clear();
bool IsInitialized() const;                                                                          

int ByteSize() const;
bool MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;

3.3 嵌套类型

3.4 访问器

// optional uint32 StudentID = 1;
inline bool has_studentid() const;
inline void clear_studentid();
static const int kStudentIDFieldNumber = 1;
inline ::google::protobuf::uint32 studentid() const;
inline void set_studentid(::google::protobuf::uint32 value);

// optional string Name = 2;
inline bool has_name() const;                                
inline void clear_name();
static const int kNameFieldNumber = 2;
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);

// optional uint32 Score = 3;                            
inline bool has_score() const;
inline void clear_score();
static const int kScoreFieldNumber = 3;
inline ::google::protobuf::uint32 score() const;
inline void set_score(::google::protobuf::uint32 value);

protocol
buffer编译器会针对各级一个字段生成有getset主意,这些措施的号采用标识符所有小写加上相应的前缀或后缀组成.生成一个值为Tags的k标识符FieldNum常量,

3.5 其他函数

除开生成上述项目的法子外, 编译器还会扭转有用以信息类型处理的私有方法.
每一个.proto文本于编译的时还见面自动包含message.h文件,这个文件宣称了许多序列化和反序列化,调试,
复制合并等息息相关的方法.

3.6 使用例子

于我们平常的行使中,通常一个message对应一个像样,在相应的接近吃定义一个set和create方法来变化与剖析PB信息.针对上述消息定义如下类:

// test.h
class CStudent
{
public:
    unsigned    mStudentID;
    unsigned    mScore;
    string      mName;

    CStudent()
    {
        Init();
    }

    inline void Init()
    {
        mStudentID = 0;
        mScore = 0;
        mName = "";
    }
}

class CMathScore
{
private:
    unsigned    mClassID;
    CStudent    mScoreInf[100];
public:
    CMathSCore()
    {
        Init();
    }
    ~CMathScore() {};

    void Init();
    void SetFromPB(const PBMathScore* pPB);
    void CreatePB(PBMathScore* pPB);

    // Get & Set mClassID
    ...
    // Get & set mScoreInf
    ...
    // some other function
    ...
}

对应的cpp文本中落实对PB的操作

// test.cpp
void CMathScore::Init()
{
    mClassID = 0;
    memset(mScoreInf, 0, sizeof(mScoreInf));
}

void CMathScore::SetFromPB(const PBMathScore* pPB)
{
    if ( NULL == pPB ) return;

    mClassID = pPB->classid();
    for(unsigned i = 0; i < (unsigned)pPB->scoreinf_size() && i < 100; ++i)
    {
        PBStudent* pStu = pPB->mutable_scoreinf(i);
        mScoreInf[i].mStudentID = pStu->studentid();
        mScoreInf[i].mScore        = pStu->score();
        mScoreInf[i].mName        = pStu->name();
    }
}

void CMathScore::CreatePB(PBMathScore* pPB)
{
    if ( NULL == pPB ) return;

    pPB->set_classid(mClassID);
    for(unsigned i = 0; i < 100; ++i)
    {
        PBStudent* pStu = pPB->add_scoreinf();
        pStu->set_studentid(mScoreInf[i].mStudentID)
        pStu->set_score(mScoreInf[i].mScore);
        pStu->set_name(mScoreInf[i].mName);        
    }
}

PB文件的读写

// use.cpp
#include<test.h>

#defind        MAX_BUFFER        1024 * 1024
int write()
{
    CMathScore    mMath;
    PBMathScore mPBMath;
    // use set functions to init member variable

    fstream fstm("./math.dat", ios::out | ios::binary);
    if ( fstm.is_open() == false )
    {
        return -1;
    }    
    char* tpBuffer = (char*)malloc(MAX_BUFFER);
    if ( NULL == tpBuffer )
    {
        return -2;
    }

    mMath.CreatePB(&mPBMath);
    if ( mPBMath.SerializeToArray(tpBuffer, mPBMath.ByteSize()) == false )
    {
        return -3;
    }
    fstm.write(tpBuffer, mPBMath.ByteSize());
    free(tpBuffer);
    fstm.close();

    return 0;
}

int read()
{
    CMathScore    mMath;
    PBMathScore mPBMath;

    fstream fstm.open("./math.dat", ios::out | ios::binary);
    if ( fstm.is_open() == false )
    {
        return -1;
    }    
    char* tpBuffer = (char*)malloc(MAX_BUFFER);
    if ( NULL == tpBuffer )
    {
        return -2;
    }
    char*    tpIdx = tpBuffer;
    int     tLen;
    while ( !fstm.eof() && tLen < MAX_BUFFER )
    {
        fstm.read(tpIdx, 1);
        tpIdx += 1;
        tLen++;
    }
    if ( mPBMath.ParseFromArray(tpBuffer, tLen - 1) == false )
    {
        return -3;
    }
    fstm.close();
    free(tpBuffer);
    tpIdx = NULL;

    mMath.SetFromPB(&mPBMath);
    // do some thing

    return 0;
}

1.下载安装:

google protocol
buffer 的官网地址是:http://code.google.com/p/protobuf/

        建议下充斥稳定版本:protobuf-2.4.1  linux下充斥protobuf-2.4.1.tar.bz2
  windows下充斥protobuf-2.4.1.zip

此坐linux下安装为实例:

tar -xvf protobuf-2.4.1.tar.bz2

cd protobuf-2.4.1

./configure
–prefix=/usr/local/protobuf-2.4.1

make

make install

 

2.使用protobuf

查看编译生成的目

cd /usr/local/protobuf-2.4.1

ls

bin  include  lib

中,bin中之protoc是.proto文件的计算机,可用之家伙生成cpp,Java,Python文件.

由系统常用之家伙,可以以那个ln或者直接拷贝到网环境bin下

ln
-s /usr/local/protobuf-2.4.1/bin/protoc /usr/bin/protoc

平,可以将头文件ln或者直接拷贝到网环境

ln
-s /usr/local/protobuf-2.4.1/include/google /usr/include/google

拿lib文件ln或者直接拷贝到系统环境

稍稍,方法与上.

此时刻,protobuf的开条件已搭建了.

3.安以protobuf

[cpp] view
plain
copy

  1. 数据结构体:  
  2.     message message_name{message_body;}  
  3.     message_body格式:  
  4.         例如required int32 query = 1[defaut=10];  
  5.         形式为:rule type name = value[other_rule];  
  6. 规则:  
  7.     required代表要具备该值域;  
  8.     optional表示可选的值域;  
  9.     repeated表示只是再的值域(即>=0);  
  10.     其中requered/optional是常用rule,而repeated则免常用同时因凡历史遗留现使用repeated int32 samples=4[packed=true];形式;  
  11.   
  12. value值:  
  13.     value值最小吗1,是脚编码时行使中1-15占有一号,>15虽说会占据大半各类;  
  14.     不同之message中的value值互不干扰,常因1上马计数。  
  15.   
  16. 数据类型之核心项目:  
  17. .proto Type             C++ Type            Java Type   
  18. double                  double              double   
  19. float                   float               float   
  20. int32                   int32               int   
  21. int64                   int64               long   
  22. uint32                  uint32              int   
  23. uint64                  uint64              long   
  24. sint32                  int32               int   
  25. sint64                  int64               long   
  26. fixed32                 uint32              int   
  27. fixed64                 uint64              long   
  28. sfixed32                int32               int   
  29. sfixed64                int64               long   
  30. bool                    bool                boolean   
  31. string                  string              String   
  32. bytes                   string              ByteString   
  33.   
  34. 数据类型之复杂类型:  
  35.     复杂类型主要概括:枚举,其他message,groups等。  
  36.     枚举定义例如:enum Corpus{WEB=0;LOCAL=1}  
  37.         枚举定义在message中。  
  38.         可以行使外message作为项目来定义成员。  
  39.         groups我之知有些像C++中的union结构。  
  40.   
  41. 嵌套定义:  
  42.     可以嵌套定义message结构,而嵌套定义之message被外message作为成员类型时得形式为outmessage.inmessage形式。  
  43.   
  44. 包结构:  
  45.     定义形式:package foo.bar;  
  46.     对应C++中则颇成稀个命名空间foo和bar,且bar定义在foo中;  
  47.     可以由此import “myproject/other_protos.proto”;来引入.proto文件;  
  48.     引用其他package中message时需要完整的package路径;  
  49.   
  50. Services:  
  51.     主要用于RPC系统受,在.proto中定义接口;  
  52.     定义形式而例子:  
  53.     service SearchService {  
  54.         rpc Search(SearchRequest) return (SearchResponse);  
  55.     }  
  56.   
  57. .proto文件编译:  
  58.     格式:  
  59.         protoc -–proto_path=(.proto文件路径) -–cpp_out=(.cc .java生成文件路径) (.proto文件路径)/?.proto  
  60.         -–proto_path  简化为:  –I  
  61.         其中可因需要变更:cpp_out选项为java_out/python_out。  
  62.     例子:  
  63.         protoc -I=./ –cpp_out=./ model.proto  

我们拿个例子:

建立model.proto

[cpp] view
plain
copy

  1. package cn.vicky.model.seri;  
  2.   
  3. message User {  
  4.     required int32 id = 1; // 主键,唯一  
  5.     required string username = 2; // 帐号  
  6.     required string password = 3; // 密码  
  7.     optional string email = 4; // 邮箱(可选)  
  8.     repeated Person person = 5; // 账户所有的角色(可以又)  
  9. }  
  10.   
  11. message Person {   
  12.     required int32 id = 1; // 主键,唯一  
  13.     required string name = 2; // 角色名字  
  14.   
  15.     repeated PhoneNumber phone = 3; // 电话号码(可以再次)  
  16. }   
  17.   
  18. // 枚举类型  
  19. enum PhoneType {   
  20.     MOBILE = 0;   
  21.     HOME = 1;   
  22.     WORK = 2;   
  23. }   
  24.   
  25. message PhoneNumber {   
  26.     required string number = 1;   
  27.     optional PhoneType type = 2 [default = HOME];   
  28. }   
protoc -I=./ --cpp_out=./ model.proto

将转对应的model.pb.h  model.pb.cc

使用:

编写main.cpp

[cpp] view
plain
copy

  1. /*  
  2.  * File:   main.cpp 
  3.  * Author: Vicky.H 
  4.  * Email:  eclipser@163.com 
  5.  */  
  6. #include <iostream>  
  7. #include <fstream>  
  8. #include “model.pb.h”  
  9.   
  10. /* 
  11.  *  
  12.  */  
  13. int main(void) {  
  14.   
  15.     // 创建User对象  
  16.     cn::vicky::model::seri::User u;  
  17.     u.set_id(1);  
  18.     u.set_username(“Jack”);  
  19.     u.set_password(“123456”);  
  20.     u.set_email(“289997171@qq.com”);  
  21.   
  22.     // 创建User中之一个角色  
  23.     cn::vicky::model::seri::Person* _person1 = u.add_person();  
  24.     _person1->set_id(1);  
  25.     _person1->set_name(“P1”);  
  26.   
  27.     // 创建角色遭的一个电话号码:1  
  28.     cn::vicky::model::seri::PhoneNumber* _phone1 = _person1->add_phone();  
  29.     _phone1->set_number(“+8613618074943”);  
  30.     _phone1->set_type(cn::vicky::model::seri::MOBILE);  
  31.   
  32.     // 创建角色中的一个电话号码:2  
  33.     cn::vicky::model::seri::PhoneNumber* _phone2 = _person1->add_phone();  
  34.     _phone2->set_number(“02882334717”);  
  35.     _phone2->set_type(cn::vicky::model::seri::WORK);  
  36.   
  37.   
  38.     // 创建User中之一个角色  
  39.     cn::vicky::model::seri::Person* _person2 = u.add_person();  
  40.     _person2->set_id(2);  
  41.     _person2->set_name(“P2”);  
  42.   
  43.     // 创建角色被的一个电话号码:1  
  44.     cn::vicky::model::seri::PhoneNumber* _phone3 = _person2->add_phone();  
  45.     _phone3->set_number(“+8613996398667”);  
  46.     _phone3->set_type(cn::vicky::model::seri::MOBILE);  
  47.   
  48.     // 创建角色遭的一个电话号码:2  
  49.     cn::vicky::model::seri::PhoneNumber* _phone4 = _person2->add_phone();  
  50.     _phone4->set_number(“02882334717”);  
  51.     _phone4->set_type(cn::vicky::model::seri::WORK);  
  52.   
  53.   
  54.     // 持久化:  
  55. //    std::fstream out(“User.pb”, std::ios::out | std::ios::binary | std::ios::trunc);  
  56. //    u.SerializeToOstream(&out);  
  57. //    out.close();  
  58.   
  59.     // 对象化:  
  60.     cn::vicky::model::seri::User u2;  
  61.     std::fstream in(“User.pb”, std::ios::in | std::ios::binary);  
  62.     if (!u2.ParseFromIstream(&in)) {  
  63.         std::cerr << “Failed to parse User.pb.” << std::endl;  
  64.         exit(1);  
  65.     }  
  66.       
  67.     std::cout << u2.id() << std::endl;  
  68.     std::cout << u2.username() << std::endl;  
  69.     std::cout << u2.password() << std::endl;  
  70.     std::cout << u2.email() << std::endl;  
  71.   
  72.     std::cout << “—————————” << std::endl;  
  73.     for(int i = 0;i < u2.person_size();i++) {  
  74.         cn::vicky::model::seri::Person* p = u2.mutable_person(i);  
  75.         std::cout << p->id() << std::endl;  
  76.         std::cout << p->name() << std::endl;  
  77.         for (int j = 0;j < p->phone_size();j++) {  
  78.             cn::vicky::model::seri::PhoneNumber* phone = p->mutable_phone(j);  
  79.             std::cout << phone->number() << std::endl;  
  80.         }  
  81.         std::cout << “—————————” << std::endl;  
  82.     }  
  83.     return 0;  
  84. }  

需 -lpthread -lprotobuf        
 (protobuf已经为加载到了/usr/lib)

推行后,会变:User.pb,存储的二进制文件.可以一直打开看看.

以上,我们运用了protobuf完成c++下的目标序列化以及反序列化.这里我们要描述一下protobuf的优势了.

那么即便是protobuf性能高效,他的序列化速度比java自身的序列化还抢数倍,而且支持3种植语言对象的转换.以往,在C++中序列化的目标,比
如用boost
serialization持久化的靶子,无法用java展开,即便使用jni技术,这为是坏累的事.现在我们出protobuf了.

运行: protoc -I=./ –java_out=./ model.proto 将转对应之Java类

我们可以为此Maven建立一个Java工程.需要protobuf的java依赖库:

[html] view
plain
copy

  1. <project xmlns=”http://maven.apache.org/POM/4.0.0″ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”  
  2.          xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.   
  5.     <groupId>cn.vicky</groupId>  
  6.     <artifactId>google_protobuf_01_java</artifactId>  
  7.     <version>1.0-SNAPSHOT</version>  
  8.     <packaging>jar</packaging>  
  9.   
  10.     <name>google_protobuf_01_java</name>  
  11.     <url>http://maven.apache.org&lt;/url&gt;  
  12.   
  13.     <properties>  
  14.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  15.     </properties>  
  16.   
  17.     <dependencies>  
  18.         <dependency>  
  19.             <groupId>com.google.protobuf</groupId>  
  20.             <artifactId>protobuf-java</artifactId>  
  21.             <version>2.4.1</version>  
  22.         </dependency>  
  23.     </dependencies>  
  24. </project>  
编写Test.java

[java] view
plain
copy

  1. package cn.vicky.model.seri;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8.   
  9. /** 
  10.  * 
  11.  * @author Vicky.H 
  12.  */  
  13. public class Test {  
  14.   
  15.     public static void main(String args[]) throws FileNotFoundException, IOException {  
  16.         File file = new File(“User.pb”);  
  17.         InputStream is = new FileInputStream(file);  
  18.         Model.User user = Model.User.parseFrom(is);  
  19.         System.out.println(user.getId());  
  20.         System.out.println(user.getUsername());  
  21.         System.out.println(user.getPassword());  
  22.         System.out.println(user.getEmail());  
  23.         System.out.println(“——————-“);  
  24.         for (Model.Person person : user.getPersonList()) {  
  25.             System.out.println(person.getId());  
  26.             System.out.println(person.getName());  
  27.             for (Model.PhoneNumber phone : person.getPhoneList()) {  
  28.                 System.out.println(phone.getNumber());  
  29.             }  
  30.             System.out.println(“——————-“);  
  31.         }  
  32.         is.close();  
  33.     }  
  34. }  

运行:

1
Jack
123456

289997171@qq.com

1
P1
+8613618074943

02882334717

2
P2
+8613996398667

02882334717

运行 SUCCESSFUL (总时间:  594ms)

OK.以上我们成功了probuf在C++,Java的使用.非常强力是勿是!!

计划思想:

当POJO中,protobuf生成的好像,处于PO状态,而且是变化的近乎,我们绝不要做另外改动要最好的改,那么,这个时,我们得以经过C++友元类的方,为PO添加一个JO类.将数据结构算法暌违,也就是说,PO是数量,JO放算法!!!

与数据库的结合:

MySQL
oracle
可以死轻松的积存,读取二向前制.还有少数,那就是是透过这种艺术,我们好非常简单的以C++的靶子,持久化的redis之类内存数据库了.

附:

model.proto也得以这么定义,不过,本人看,上面的重好,这里才供参考,采用什么的主意,生成的好像的布局也未极端一样.

[cpp] view
plain
copy

  1. package cn.vicky.model.seri;  
  2.   
  3. message User {  
  4.     required int32 id = 1; // 主键,唯一  
  5.     required string username = 2; // 帐号  
  6.     required string password = 3; // 密码  
  7.     optional string email = 4; // 邮箱(可选)  
  8.   
  9.     message Person {   
  10.         required int32 id = 1; // 主键,唯一  
  11.         required string name = 2; // 角色名  
  12.   
  13.         // 枚举类型  
  14.         enum PhoneType {   
  15.             MOBILE = 0;   
  16.             HOME = 1;   
  17.             WORK = 2;   
  18.         }   
  19.   
  20.         message PhoneNumber {   
  21.             required string number = 1;   
  22.             optional PhoneType type = 2 [default = HOME];   
  23.         }   
  24.   
  25.         repeated PhoneNumber phone = 3; // 电话号码(可以更)  
  26.     }   
  27.   
  28.     repeated Person person = 5; // 账户有的角色(可以再次)  
网站地图xml地图