protocol buffer rpc

2019-12-13 16:14:45  

  最近由于公司项目需求,需要实现基于google的protocol buffer实现rpc远程调用。本文主要讲解如何使用.proto文件生成.pb.cc和.pb.h代码,以及如何利用生成的代码用户实现自己的rpc调用。

1、编写proto文件

  proto的具体语法可以看Google官方的文档,基本的语法不再解释。链接:https://developers.google.com/protocol-buffers/docs/cpptutorial 

  下面看看proto文件如何书写实现rpc服务。

syntax = "proto3";                /*声明使用protocol buffer的版本3.0以上*/

option cc_generic_services = true;       /*生成C++代码的services*/

/*No parameters request*/
message NoParametersRequest {          /*以request结尾的message都表示输入性参数,NoParameterRequest表示该参数没有变量(void类型)*/

}

/*CurrentStatus*/ message SwPackageStateTypeResponse{ /*以response结尾的message表示输出型参数或者函数的返回值*/ enum SwPackageStateType { kTransferring = 0; kTransferred = 1; kProcessing = 2; kProcessed = 3; } SwPackageStateType state_type = 1 ; /*定义枚举类型*/ }
/*下面实现一个数组vector功能的参数*/
/*GetSwClusterInfo*/ message SwClusterInfo { /*消息有三个字段name,version,state_type,每个字段后面的数字表示唯一表示在消息定义中,每个字段都有唯一的一个数字标识符*/ string name = 1; string version = 2; enum SwClusterStateType { kPresent = 0; kAdded = 1; kUpdated = 2; kRemoved = 3; } SwClusterStateType state_type = 3; } message GetSwClusterInfoResponse { repeated SwClusterInfo swcluster_info = 1; /*repeated 关键字表示变量是一个数组或者vector*/ }

/*GetHistory*/
  message GetHistoryRequest {
    uint64 timestamp_ge = 1;
    uint64 timestamp_lt = 2;
  }

 
 

  message ActionType{
    enum KActionType{
      kUpdate = 0;
      kInstall =1;
      kRemove = 2;
    }
  }
  message ResultType{
    enum KResultType{
      kSuccessfull = 0;
      kFailed =1;
    }
  }
  message GetHistoryVectorType{
    uint64 time = 1;
    string name = 2;
    string version = 3;
    ActionType action = 4;
    ResultType resolution = 5;
  }
  message GetHistoryResponse{
    repeated GetHistoryVectorType history = 1;
  }

/*主要看看这个实现rpc服务*/
service PackageManagementService {  /*服务名称*/

  /*实现3个rpc调用,第一个rpc,CurrentStatus表示方法名称,NoParametersRequest输入性参数,SwPackageStateTypeResponse输出型参数或者函数返回值*/ rpc CurrentStatus(NoParametersRequest) returns(SwPackageStateTypeResponse); rpc GetSwClusterInfo(NoParametersRequest) returns(GetSwClusterInfoResponse);
   rpc GetHistory(GetHistoryRequest) returns(GetHistoryResponse); }

2、分析proto文件生成.pb.cc和.pb.h的代码

  代码生成器的安装及使用可以去Google官方查看。

  通过这个命令: protoc package_management.proto --cpp_out=.  下面分析一下生成的代码:

  1、SwPackageStateTypeResponse类的部分代码

 1   /*通过枚举的值,获取枚举的名称*/
 2   static inline const std::string& SwPackageStateType_Name(T enum_t_value) {
 3     static_assert(::std::is_same<T, SwPackageStateType>::value ||
 4       ::std::is_integral<T>::value,
 5       "Incorrect type passed to function SwPackageStateType_Name.");
 6     return SwPackageStateTypeResponse_SwPackageStateType_Name(enum_t_value);
 7   }
   /*通过枚举的名称,获取枚举的值*/
8 static inline bool SwPackageStateType_Parse(const std::string& name, 9 SwPackageStateType* value) { 10 return SwPackageStateTypeResponse_SwPackageStateType_Parse(name, value); 11 } 12 13 // accessors ------------------------------------------------------- 14 15 enum : int { 16 kStateTypeFieldNumber = 1, 17 }; 18 // .SwPackageStateTypeResponse.SwPackageStateType state_type = 1;
   /*清空state_type*/ 19 void clear_state_type();
   /*获取state_type的值*/
20 ::SwPackageStateTypeResponse_SwPackageStateType state_type() const;
   /*设置state_type的值*/
21 void set_state_type(::SwPackageStateTypeResponse_SwPackageStateType value); 22 private: 23 ::SwPackageStateTypeResponse_SwPackageStateType _internal_state_type() const; 24 void _internal_set_state_type(::SwPackageStateTypeResponse_SwPackageStateType value); 25 public:

  2、GetSwClusterInfoResponse类对数组vector操作的代码部分代码

 1   enum : int {
 2     kSwclusterInfoFieldNumber = 1,
 3   };
 4   // repeated .SwClusterInfo swcluster_info = 1;
 5   int swcluster_info_size() const;
 6   private:
 7   int _internal_swcluster_info_size() const;
 8   public:
 9   void clear_swcluster_info();
   /*获取vector的值*/
10 ::SwClusterInfo* mutable_swcluster_info(int index); 11 ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::SwClusterInfo >* 12 mutable_swcluster_info(); 13 private: 14 const ::SwClusterInfo& _internal_swcluster_info(int index) const; 15 ::SwClusterInfo* _internal_add_swcluster_info(); 16 public: 17 const ::SwClusterInfo& swcluster_info(int index) const;
   /*增加vector的值*/
18 ::SwClusterInfo* add_swcluster_info(); 19 const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::SwClusterInfo >& 20 swcluster_info() const; 21 22 // @@protoc_insertion_point(class_scope:GetSwClusterInfoResponse) 23 private: 24 class _Internal; 25 26 ::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_; 27 ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::SwClusterInfo > swcluster_info_; 28 mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; 29 friend struct ::TableStruct_package_5fmanagement_2eproto; 30 };

3、利用生成的代码用户实现rpc服务

  具体的protocol buffer内部rpc的机制这里不描述了,这里说明用户需要实现的代码。

  1、service端,用户需要继承PackageManagementService,实现具体的rpc调用代码

 1 class PackageManagementServiceImpl : public PackageManagementService {
 2 
 3     public:
 4     PackageManagementServiceImpl(){
 5 
 6         std::cout <<"PackageManagementServiceImpl structure "<<std::endl;
 7     }
 8     ~PackageManagementServiceImpl(){
 9 
10         std::cout <<"PackageManagementServiceImpl desstructure "<<std::endl;
11     }
12 
13     virtual void CurrentStatus(::google::protobuf::RpcController* controller,
14                        const ::NoParametersRequest* request,
15                        ::SwPackageStateTypeResponse* response,
16                        ::google::protobuf::Closure* done);
17 
18     virtual void GetSwClusterInfo(::google::protobuf::RpcController* controller,
19                        const ::NoParametersRequest* request,
20                        ::GetSwClusterInfoResponse* response,
21                        ::google::protobuf::Closure* done);
22 
23 };
 1 void PackageManagementServiceImpl :: CurrentStatus(::google::protobuf::RpcController* controller,
 2                    const ::NoParametersRequest* request,
 3                    ::SwPackageStateTypeResponse* response,
 4                    ::google::protobuf::Closure* done){
 5 
 6     std::cout << "CurrentStatus" <<std::endl;
 7     const std::string enum_name = "kTransferring";
 8     
 9     SwPackageStateTypeResponse_SwPackageStateType  value;
10     response->SwPackageStateType_Parse(enum_name, &value);
11     /*做具体的数据赋值*/
12     response->set_state_type(value);
13 }
14 
15 void PackageManagementServiceImpl::GetSwClusterInfo(::google::protobuf::RpcController* controller,
16                    const ::NoParametersRequest* request,
17                    ::GetSwClusterInfoResponse* response,
18                    ::google::protobuf::Closure* done){
19 
20 
21     std::cout << "GetSwClusterInfo" <<std::endl;
22 
23     SwClusterInfo *swcluster_info ;
24    /*向vector里添加数据*/
25     swcluster_info = response->add_swcluster_info();
26 
27     swcluster_info->set_name("ICC");
28     swcluster_info->set_version("1.1");
29 
30     swcluster_info = response->add_swcluster_info();
31     swcluster_info->set_name("ICM");
32     swcluster_info->set_version("1.2");
33 
34 
35     swcluster_info= response->add_swcluster_info();
36 
37     swcluster_info->set_name("SOTA");
38     swcluster_info->set_version("1.3");
39 
40                  
41 }

  2、客户端代码

 1 TEST(CurrentStatus, PackageManagement) {
 2     
 3     RpcChannel channel;
 4     PackageManagementService::Stub package_manage_client(&channel);
 5 
 6     NoParametersRequest request;
 7     SwPackageStateTypeResponse response;
 8 
 9     package_manage_client.CurrentStatus(nullptr, &request, &response, nullptr);
10   /*解析rpc调用返回的数据*/
11     SwPackageStateTypeResponse_SwPackageStateType  value;
12     value = response.state_type();
13 
14     ASSERT_EQ(value, 0);
15 
16 }
17 
18 TEST(GetSwClusterInfo, PackageManagement) {
19     
20     RpcChannel channel;
21     PackageManagementService::Stub package_manage_client(&channel);
22 
23     NoParametersRequest request;
24     GetSwClusterInfoResponse  response;
25     
26     std::cout <<"GetSwClusterInfo RPC "<<std::endl;
27     package_manage_client.GetSwClusterInfo(nullptr, &request, &response, nullptr);
28 
29     int vector_num = response.swcluster_info_size();
30     ASSERT_EQ(vector_num, 3);
31   /*遍历和解析vector数据*/
32     ::google::protobuf::RepeatedPtrField< ::SwClusterInfo > *swcluster_info_parse = response.mutable_swcluster_info();
33 
34     ::google::protobuf::RepeatedPtrField< ::SwClusterInfo >::iterator it = swcluster_info_parse->begin();
35 
36     std::string name;
37     std::string version;
38     
39     name = swcluster_info_parse->at(0).name();
40     ASSERT_STREQ(name.c_str(), "ICC");
41     
42     version = swcluster_info_parse->at(0).version();
43     ASSERT_STREQ(version.c_str(), "1.1");
44     
45 
46     name = swcluster_info_parse->at(1).name();
47     ASSERT_STREQ(name.c_str(), "ICM");
48     
49     version = swcluster_info_parse->at(1).version();
50     ASSERT_STREQ(version.c_str(), "1.2");
51 
52     name = swcluster_info_parse->at(2).name();
53     ASSERT_STREQ(name.c_str(), "SOTA");
54     
55     version = swcluster_info_parse->at(2).version();
56     ASSERT_STREQ(version.c_str(), "1.3");
57 
58     
59     /*遍历数据*/
60     for( ; it != swcluster_info_parse->end(); ++it ){
61 
62         std::cout << "name = " << it->name() <<std::endl;
63         std::cout << "version = " << it->version() <<std::endl;
64 
65     }
66 }

猜你喜欢

转载自www.cnblogs.com/show-hand/p/12033836.html