定义service

.proto文件的代码如下:

syntax = "proto3"; // 声明了protobuf的版本

package fixbug; // 声明了代码所在的包(对于C++来说是namespace)

//定义下面的选项,表示生成service服务类和rpc方法描述,默认不生成
option cc_generic_services = true;

message ResultCode//封装一下失败类
{
    int32 errcode = 1;//表示第1字段
    bytes errmsg = 2;//表示第2字段
}

// 定义登录请求消息类型  name   pwd
message LoginRequest
{
    bytes name = 1;//表示第1字段
    bytes pwd = 2;//表示第2字段
}

// 定义登录响应消息类型
message LoginResponse
{
    ResultCode result = 1;//表示第1字段
    bool success = 2;//表示第2字段
}

//在protobuf里面怎么定义描述rpc方法的类型 - service
service UserServiceRpc
{
    rpc Login(LoginRequest) returns(LoginResponse);
}

其中,涉及到service的部分如下:

//定义下面的选项,表示生成service服务类和rpc方法描述,默认不生成
option cc_generic_services = true;
//在protobuf里面怎么定义描述rpc方法的类型 - service
service UserServiceRpc
{
    rpc Login(LoginRequest) returns(LoginResponse);
}

UserServiceRpc类 和 UserServiceRpc_stub类

对上文的.proto文件保存并编译,得到一个.pb.h和一个.pb.cc文件,包含UserServiceRpc类和UserServiceRpc_stub类。

UserServiceRpc类分析

UserServiceRpc类是因为在.proto文件中定义了UserServiceRpc服务而生成的,UserServiceRpc类继承于google::protobuf::Service类,如下所示:
在这里插入图片描述

UserServiceRpc类成员如下:

class UserServiceRpc : public ::PROTOBUF_NAMESPACE_ID::Service {
 protected:
  // This class should be treated as an abstract interface.
  inline UserServiceRpc() {};
 public:
  virtual ~UserServiceRpc();

  typedef UserServiceRpc_Stub Stub;

  static const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor* descriptor();

  virtual void Login(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
                       const ::fixbug::LoginRequest* request,
                       ::fixbug::LoginResponse* response,
                       ::google::protobuf::Closure* done);

  // implements Service ----------------------------------------------

  const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor* GetDescriptor();
  void CallMethod(const ::PROTOBUF_NAMESPACE_ID::MethodDescriptor* method,
                  ::PROTOBUF_NAMESPACE_ID::RpcController* controller,
                  const ::PROTOBUF_NAMESPACE_ID::Message* request,
                  ::PROTOBUF_NAMESPACE_ID::Message* response,
                  ::google::protobuf::Closure* done);
  const ::PROTOBUF_NAMESPACE_ID::Message& GetRequestPrototype(
    const ::PROTOBUF_NAMESPACE_ID::MethodDescriptor* method) const;
  const ::PROTOBUF_NAMESPACE_ID::Message& GetResponsePrototype(
    const ::PROTOBUF_NAMESPACE_ID::MethodDescriptor* method) const;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UserServiceRpc);
};

  • Login()虚函数,让派生类重写。我们看到,Login虚函数的名字就是我们定义的rpc服务的方法的名字,其有4个固定的参数。
  • GetDescriptor()函数,获得一个指向ServiceDescriptor类型对象的指针,ServiceDescriptor类型的对象中描述了rpc方法的名字(属于哪一个类类型的方法)和调用函数方法的参数。

UserServiceRpc_stub类分析

UserServiceRpc_stub类继承了UserServiceRpc类,并重写了UserServiceRpc类中的虚函数Login()。
在这里插入图片描述
UserServiceRpc_stub类成员如下:

class UserServiceRpc_Stub : public UserServiceRpc {
 public:
  UserServiceRpc_Stub(::PROTOBUF_NAMESPACE_ID::RpcChannel* channel);
  UserServiceRpc_Stub(::PROTOBUF_NAMESPACE_ID::RpcChannel* channel,
                   ::PROTOBUF_NAMESPACE_ID::Service::ChannelOwnership ownership);
  ~UserServiceRpc_Stub();

  inline ::PROTOBUF_NAMESPACE_ID::RpcChannel* channel() { return channel_; }

  // implements UserServiceRpc ------------------------------------------

  void Login(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
                       const ::fixbug::LoginRequest* request,
                       ::fixbug::LoginResponse* response,
                       ::google::protobuf::Closure* done);
 private:
  ::PROTOBUF_NAMESPACE_ID::RpcChannel* channel_;
  bool owns_channel_;
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UserServiceRpc_Stub);
};
  • 其拥有一个RpcChannel类型的指针变量,在构造时需要传入这个值(没有默认构造函数!)。
  • 其Login()是继承自基类的函数,其调用了channel的CallMethod函数,Login()的实现如下:
void UserServiceRpc_Stub::Login(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
                              const ::fixbug::LoginRequest* request,
                              ::fixbug::LoginResponse* response,
                              ::google::protobuf::Closure* done) {
  channel_->CallMethod(descriptor()->method(0),
                       controller, request, response, done);
}

Rpcchannel类

Rpcchannel是一个抽象类!其包含一个CallMethod()虚函数。
在这里插入图片描述
Rpcchannel类代码如下:
在这里插入图片描述
因此我们必须自己去实现一个类,这个类从Rpcchannel继承而来,并重写CallMethod()虚函数。即:

在这里插入图片描述
由于派生类是可以用基类指针的(多态),因此stub桩类不管调用哪个方法,最终都调用到我们的MyRpcChannel的CallMethod方法,我们在这里就可以进行rpc方法的序列化和反序列化,然后发起远程的rpc调用请求。所以框架的实现重点就在于RpcChannel的CallMethod方法

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐