无论什么语言,实现grpc的核心是.proto文件,通过protoc命令将.proto文件生成grpc框架的接口文件*gb*, 该文件中包含.proto定义的方法及参数接口,服务器,客户端相关操作接口;然后再编写服务器,客户端代码,调用*gb*文件生成的接口。
直接实例代码介绍其过程:
核心文件:hello.proto
syntax = "proto3"; // 规定使用proto3的语法
service MsgService { // 定义服务, 流数据放到括号里面rpc GetMsg (MsgRequest) returns (MsgResponse){}
}message MsgRequest { // 请求的结构, 也可以定义int32,int64,double,float等数据类型, 等号后面的数字表示第几个string name = 1;
}message MsgResponse { // 回应的结果string msg = 1;
}
然后执行:
protoc -I . --cpp_out=. ./hello.proto#生成hello.pb.cc文件protoc -I . --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ./hello.proto#生成hello.grpc.pb.cc文件
或者
protoc -I . --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ./hello.proto#一起生成两个文件-I :(-IPATH)指定要在其中搜索导入(import)的目录。可指定多次,目录将按顺序搜索。如果没有给出,则使用当前工作目录。
--cpp_out = . : 以c++语言格式输出,等号后面为输出文件存放的路径
--grpc_out = . :输出grpc框架接口文件。等号后面为输出文件存放的路径
--plugin=`which grpc_cpp_plugin` :指定一个protobuf插件(grpc_cpp_plugin)来生成grpc代码。hello.proto : 核心文件,可以是路径./hello.proto,或者绝对路径。
执行成功后,指定的目录下会生成两个文件:
hello_pb.cc/hello_pb.h:主要是对参数(MsgRequest,MsgResponse)的属性设置,参数类的重定向,参数成员的设置,获取等操作。
hello_pb_grpc.cc/hello_grpc_pb.h :该文件生成了proto方法(GetMsg)的属性操作接口,通过该存根实现服务器与客户端的通讯
生成这两个文件之后就可以编写服务器,客户端代码了:
服务器代码(hello_server.cc):
#include <iostream>
#include <memory>
#include <string>#include <grpcpp/grpcpp.h>#include "hello.grpc.pb.h"
#include "hello.pb.h"using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;//创建类,继承MsgService::Service, 父类在生成的hello.grpc.pb.cc/h文件中,属于grpc的服务端接口类
class MyServer final : public MsgService::Service{Status GetMsg(ServerContext* context, const MsgRequest* request, MsgResponse* reply) override{//hello.grpc.pb文件生成的类接口std::string str("Hello ");reply->set_msg( str + request->name());//hello.pb文件生成的类接口,设置回复结构的成员数据return Status::OK;}
};void RunServer(){std::string server_address("0.0.0.0:50051");MyServer service;ServerBuilder builder;builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());builder.RegisterService(&service);std::unique_ptr<Server> server(builder.BuildAndStart());std::cout << "server listen on ..." << server_address << std::endl;server->Wait();
}int main(int argc, char **argv)
{RunServer();return 0;
}
客户端:
#include <iostream>
#include <memory>
#include <string>#include <grpcpp/grpcpp.h> // 和python一样, import grp// 在包含两个信息和应用的头文件
#include "hello.grpc.pb.h"
#include "hello.pb.h"// 这是通用工具
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;class MsgServiceClient {public:MsgServiceClient(std::shared_ptr<Channel> channel): stub_(MsgService::NewStub(channel)) {}MsgResponse GetMsg(const std::string& user, int num1, double num2) {// 请求数据数据格式化到requestMsgRequest request; request.set_name(user);request.set_num1(num1);request.set_num2(num2);// 服务器返回端MsgResponse reply;//客户端上下文。它可以用来传递额外的信息//服务器和/或调整某些RPC行为。ClientContext context;// The actual RPC.Status status = stub_->GetMsg(&context, request, &reply);if (status.ok()) {return reply;} else {std::cout << status.error_code() << ": " << status.error_message()<< std::endl;return reply;}}private:std::unique_ptr<MsgService::Stub> stub_;
};int main(int argc, char** argv) {MsgServiceClient z_msg(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));std::string user("world");MsgResponse reply = z_msg.GetMsg(user);std::cout<<reply.msg()<<std::endl;printf("num1 = %d; num2=%f\n", reply.num1(), reply.num2());return 0;
}
cmake编译:
CMakeLists.txt编写:
cmake_minimum_required(VERSION 3.5)
project(test2)include(/XXX/gRPC/grpc/examples/cpp/cmake/common.cmake)#调用grpc环境配置,该路径为绝对路径set(PWDIR ${CMAKE_CURRENT_SOURCE_DIR})
set(GRPCDIR "/XXX/gRPC/grpc/cmake/build/_install")#编译grpc时指定的安装路径include_directories(${PWDIR}${GRPCDIR}/include
)link_directories(${GRPCDIR}/lib
)add_library(hw_grpc_proto"${PWDIR}/hello.grpc.pb.cc""${PWDIR}/hello.pb.cc"
)
target_link_libraries(hw_grpc_proto protobuf protobuf-lite protoc grpc++_reflection gRPC::grpc++)foreach(_targethello_server hello_client)add_executable(${_target} "${_target}.cpp")target_link_libraries(${_target}hw_grpc_proto)
endforeach()
后期会发布一篇grpc程序编写的完整流程,从proto,*.pb.cc, *.grpc.pb.cc解析 到服务器 客户端代码编写,cmake编写,返回状态设置,.cmake文件解析, rpc流式传输 的全面刨析,让您一篇文章学会grpc。
感兴趣的话关注。一起交流学习。