转自:https://blog.csdn.net/nk_test/article/details/72682780
1.CallMethod
在客户端生成的存根类Stub,实际上通过callmethod来实现的调用远程方法,
void EchoService_Stub::Foo(::google::protobuf::RpcController* controller, const ::FooRequest* request, ::FooResponse* response, ::google::protobuf::Closure* done) { channel_->CallMethod(descriptor()->method(0), controller, request, response, done); }
所以框架的实现重点就在于RpcChannel的CallMethod方法,发送请求就是在这个函数中完成的。
Muduo中的CallMethod的实现:
void RpcChannel::CallMethod(const ::google::protobuf::MethodDescriptor* method, google::protobuf::RpcController* controller, const ::google::protobuf::Message* request, ::google::protobuf::Message* response, ::google::protobuf::Closure* done) { RpcMessage message; message.set_type(REQUEST); int64_t id = id_.incrementAndGet(); message.set_id(id); message.set_service(method->service()->full_name());//获取服务的方法名 message.set_method(method->name());//获取方法名 message.set_request(request->SerializeAsString()); // FIXME: error check OutstandingCall out = { response, done }; { MutexLockGuard lock(mutex_); outstandings_[id] = out; } codec_.send(conn_, message);//发送数据 }
CallMethod中除了发送数据之外,参数还有一个MethodDescriptor类,这是用来标识哪一个service的。
例如,如果定义了多个service,那么每个service的请求包和回复包都是protobuf中的message结构体,在这个例子中是EchoRequest和EchoResponse message。可是,它们仅仅是包体,也就是说,即使你发送了这些消息,在服务器端还需要一个包头来识别到底是哪个请求的包体,然后再进行具体的调用处理。如,
void EchoService::CallMethod(const ::google::protobuf::MethodDescriptor* method, ::google::protobuf::RpcController* controller, const ::google::protobuf::Message* request, ::google::protobuf::Message* response, ::google::protobuf::Closure* done) { GOOGLE_DCHECK_EQ(method->service(), EchoService_descriptor_); switch(method->index()) { case 0: Echo(controller, ::google::protobuf::down_cast<CONST ::echo::EchoRequest*>(request), ::google::protobuf::down_cast< ::echo::EchoResponse*>(response), done); break; default: GOOGLE_LOG(FATAL) << "Bad method index; this should never happen."; break; } }
//没太看懂这个callmethod,怎么是EchoService类的函数呢?那还是在客户端生成的吗?那case 0的时候调用的Echo也是客户端的代码吗?还是说也是存根stub?看起来像是,那这个Echo具体还要调用rpc的callmethod方法?这里的EchoService的callmethod只是相当于一个代理?