前言
本文主要解读RPC项目中的protobuf。为接下来项目的完成奠定重要的基础。
protobuf的定义
syntax = "proto3";
package fixbug;
//定义下面的描述,才能生成相应的service类和rpc方法描述。默认不生成
option cc_generic_services =true;
message LoginRequest{
string name=1;
string pwd=2;
}
message LoginResponse{
int32 errcode=1;
string errmsg=2;
bool success=3;
}
message ExitRequest{
string name=1;
string pwd=2;
}
message ExitResponse{
int32 errcode=1;
string errmsg=2;
bool success=3;
}
service UserServiceRpc{
rpc Login(LoginRequest) returns (LoginResponse);
rpc Exit(ExitRequest)returns (ExitResponse);
}
上面简单定义一个登录需求和退出需求,具体内部成员先不用在意。
option cc_generic_services =true;//这是一个一个常出错的地方,一定要记得设置。
protubuf不支持所谓的rpc功能,它只是对rpc的一种描述。通过描述就可以做rpc请求所携带的参数的序列化和反序列化。
protubuf不管是message还是所谓的service最后生成的c++代码都是一个类。
protobuf生成的.cc和.h文件的解读
virtual void Login(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
const ::fixbug::LoginRequest* request,
::fixbug::LoginResponse* response,
::google::protobuf::Closure* done);
virtual void Exit(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
const ::fixbug::ExitRequest* request,
::fixbug::ExitResponse* response,
::google::protobuf::Closure* done);
生成的service类有两个虚函数,也就是说这个之后是需要我们来实现的,这也就是服务的提供者,提供方需要干的事情。
我们看到还生成了一个Stub类(桩类),这是一个桩类继承于我们之前生成的UserServiceRpc类。这个类也就是服务的消费者。他是没有默认构造函数的,也就是说要想使用这个的话必须传递一个RpcChannel* channel。
class UserServiceRpc_Stub : public UserServiceRpc {
public:
UserServiceRpc_Stub(::PROTOBUF_NAMESPACE_ID::RpcChannel* channel);
.......
void Login(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
const ::fixbug::LoginRequest* request,
::fixbug::LoginResponse* response,
::google::protobuf::Closure* done);
void Exit(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
const ::fixbug::ExitRequest* request,
::fixbug::ExitResponse* response,
::google::protobuf::Closure* done);
private:
::PROTOBUF_NAMESPACE_ID::RpcChannel* channel_;
它自己内部有个成员变量RpcChannel* channel_,那么想想也知道,这个有参构造应该是接收之后给它初始化的。
我们可以看到这个桩类也有Login和Exit,让我们来看看他们俩的具体实现。
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);
}
void UserServiceRpc_Stub::Exit(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
const ::fixbug::ExitRequest* request,
::fixbug::ExitResponse* response,
::google::protobuf::Closure* done) {
channel_->CallMethod(descriptor()->method(1),
controller, request, response, done);
}
好的,那么接下来压力给到RpcChannel类的CallMethod方法,继续找发现这个RpcChannel类的CallMethod方法是个纯虚函数,这样我们就必须自己实现一个类从RpcChannel类继承而来然后把这个CallMethod方法重写一下然后传到桩类的有参构造利用多态
的特性完成调用.具体实现将在接下来几篇中完成。