Just when I thought I covered the topic of RPC in C++ with Thrift, I came across a new and very
Just like with Thrift, the first step is to define your RPC service. Here’s my definition of a simple service with one RPC method which accepts an input parameter and provides a return value:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
syntax = "proto3"; message Input { string input_msg = 1; } message Output { string output_msg = 1; } service gRPCService { rpc hello(Input) returns (Output) {} } |
I saved it as grpc_service.proto and now was the time to generate the client and server stubs. Unlike Thrift, this is a two step process: 1) you must generate the protocol buffer files, and 2) generate the gRPC client/server stubs. Both actions are done with protoc compiler and a custom plugin that comes with gRPC:
protoc -I . –cpp_out=. grpc_service.proto
protoc -I . –grpc_out=. –plugin=protoc-gen-grpc=/usr/local/bin/grpc_cpp_plugin grpc_service.proto
gRPC code generation steps.
This will compile our service definition file and produce 4 output files: .h and .cc for protocol buffer messages, and .h and .cc for gRPC client/server stubs.
Alright, that was easy. Let’s see what it takes to implement a gRPC client program… after 15 minutes reading through the documentation I came up with the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#include <iostream> #include <grpc/grpc.h> #include <grpc++/channel.h> #include <grpc++/client_context.h> #include <grpc++/create_channel.h> #include <grpc++/security/credentials.h> #include "grpc_service.grpc.pb.h" using namespace std; using namespace grpc; class gRPCClient { public: gRPCClient(shared_ptr<Channel> channel) : stub(gRPCService::NewStub(channel)) {} string hello(const std::string& msg) { Input input; Output output; ClientContext context; input.set_input_msg(msg); Status status = stub->hello(&context, input, &output); if (status.ok()) { return output.output_msg(); } else { cout << status.error_code() << ": " << status.error_message() << endl; return "RPC failed"; } } private: unique_ptr<gRPCService::Stub> stub; }; int main(int argc, char** argv) { gRPCClient client(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials())); string reply = client.hello("gRPC client says hi!"); cout << "Client received: " << reply << endl; return 1; } |
Little more code needed to construct and invoke the RPC method as compared to Thrift, but not too bad. The extra lines are mostly around creating the protocol buffer message objects and setting their properties.
The corresponding gRPC server code is pretty much just as easy to implement as with Thrift. Here’s the simple server that prints out the message it receives and sends back a reply:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include <iostream> #include <grpc/grpc.h> #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> #include <grpc++/security/server_credentials.h> #include "grpc_service.grpc.pb.h" using namespace std; using namespace grpc; class gRPCServiceImpl final : public gRPCService::Service { public: Status hello(ServerContext* context, const Input* in, Output* out) override { cout << in->input_msg() << endl; out->set_output_msg("gRPC server says hi!"); return Status::OK; } }; int main(int argc, char** argv) { gRPCServiceImpl service; ServerBuilder builder; builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials()); builder.RegisterService(&service); unique_ptr<Server> server(builder.BuildAndStart()); cout << "Server starting..." << endl; server->Wait(); return 1; } |
So there you have it folks! It is very easy to get started with this framework.
As far as which one you should prefer (Thrift vs gRPC) I can’t honestly say. I don’t know enough about them to claim one is better than the other. What I can say is that Thrift is a more mature framework that has been around for longer. You decide 🙂
P.S. On my Mac I was able to use Homebrew package manager to install the required headers/libraries/executables for gRPC. My Ubuntu 18.04 Linux has libgrpc available in its online repository. I also verified that Microsoft’s vcpkg has ports available for Windows.
Hello, i try to compile the helloworld of gRPC on codeblocks but i don’t arrive if u have an idea. I use cmake with the github repositery and i am able to compile and run client and server. But with codeblocks I add the four files generate by protoc and grpc protogen plug. I add grpc lib. Maybe there are makefile and cmakefile, but how i can to use them with codeblocks. If someone use an example of google and use codeblocks, thanks to ur answer. I try the same for others examples of multiples sources.
I have never used codeblocks; I do not know how to configure my blog examples for it. I know cmake can generate project files for Xcode where I normally work, VS, and few others. Check if cmake can produce Code::Blocks project files…
ok, to know which libs u use ? about to compile gRPC, the three of github grpc depositery grpc grpcpp and grpc++ ? or others if u write an other exemple ?
check src/CMakeLists.txt file in my github (link on the top right of the blog) repository; it will tell you what you need to link with.
OK
the link of google grpc dep ? i d’ont found ur link
pl
ok i found
i have a problem of client with error E0512 about the dns resolve i search during 4 days but don’t find maybe it’s a problem of network manager or other if u already see that, do u have an idea ?