gRPC是一个现代的、开源的、高性能远程过程调用(RPC)框架,可以在任何平台运行。gRPC使客户端和服务器端应用程序能够透明地进行通信,并简化了连接系统的构建。gRPC支持的语言包括C++、Ruby、Python、Java、Go等。
gRPC默认使用Google的Protocol Buffers,关于Protocol Buffers的介绍可以参考:https://blog.csdn.net/fengbingchun/article/details/49977903
gRPC的源码在https://github.com/grpc/grpc,最新版本的版本为v1.23.0,它的license是Apache-2.0。
关于RPC(Remote Procedure Call, 远程过程调用)的介绍可以参考:https://blog.csdn.net/fengbingchun/article/details/92406377
关于gRPC的安装可以参考:https://blog.csdn.net/fengbingchun/article/details/100608370
下面参考gRPC官方examples/cpp/helloworld中的同步模式例子,过程如下:
1. 创建IDL(interface definition language)描述文件helloworld.proto,通过protobuf定义服务端与客户端之间的RPC调用接口,通过protoc工具生成客户端和服务端代码。gRPC是需要先定义服务接口约定,才可以进行RPC调用,使用.proto可以同时定义客户端和服务端交换的数据格式以及RPC调用的接口。helloworld.proto文件内容如下:
- // Copyright 2015 gRPC authors.
- syntax = "proto3";
- option java_multiple_files = true;
- option java_package = "io.grpc.examples.helloworld";
- option java_outer_classname = "HelloWorldProto";
- option objc_class_prefix = "HLW";
- package helloworld;
- // The greeting service definition.
- service Greeter {
- // Sends a greeting
- rpc SayHello (HelloRequest) returns (HelloReply) {}
- }
- // The request message containing the user's name.
- message HelloRequest {
- string name = 1;
- }
- // The response message containing the greetings
- message HelloReply {
- string message = 1;
- }
通过protoc工具生成服务端和客户端代码,执行命令(终端定位在demo/gRGC_Test)如下:
- ./../../src/grpc/linux_install/bin/protoc --cpp_out=./ helloworld.proto
- ./../../src/grpc/linux_install/bin/protoc --grpc_out=./ --plugin=protoc-gen-grpc=./../../src/grpc/linux_install/bin/grpc_cpp_plugin helloworld.proto
会在当前目录下生成helloworld.pb.h, hellowrold.pb.cc, helloworld.grpc.pb.h, helloworld.grpc.pb.cc四个文件。使用IDL定义服务端方法、参数、返回类型,客户端和服务端都使用从服务端定义生成的接口代码。
2. 编写客户端代码,测试代码函数为test_grpc_client;
3. 编写服务端代码,测试代码函数为test_grpc_server;
- #include "funset.hpp"
- #include <iostream>
- #include <memory>
- #include <string>
- #include <grpcpp/grpcpp.h>
- #include "helloworld.grpc.pb.h"
- // reference: grpc/examples/cpp/helloworld
- namespace {
- class GreeterClient {
- public:
- GreeterClient(std::shared_ptr<grpc::Channel> channel) : stub_(helloworld::Greeter::NewStub(channel)) {}
- // Assembles the client's payload, sends it and presents the response back from the server.
- std::string SayHello(const std::string& user) {
- // Data we are sending to the server.
- helloworld::HelloRequest request;
- request.set_name(user);
- // Container for the data we expect from the server.
- helloworld::HelloReply reply;
- // Context for the client. It could be used to convey extra information to the server and/or tweak certain RPC behaviors.
- grpc::ClientContext context;
- // The actual RPC.
- grpc::Status status = stub_->SayHello(&context, request, &reply);
- // Act upon its status.
- if (status.ok()) {
- return reply.message();
- } else {
- fprintf(stderr, "error code: %d, error message: %s\n", status.error_code(), status.error_message().c_str());
- return "RPC failed";
- }
- }
- private:
- std::unique_ptr<helloworld::Greeter::Stub> stub_;
- };
- } // namespace
- int test_grpc_client()
- {
- fprintf(stdout, "client start\n");
- // Instantiate the client. It requires a channel, out of which the actual RPCs are created.
- // This channel models a connection to an endpoint (in this case, localhost at port 50051).
- // We indicate that the channel isn't authenticated(use of InsecureChannelCredentials()).
- GreeterClient greeter(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));
- std::string user("world");
- std::string reply = greeter.SayHello(user);
- fprintf(stdout, "Greeter received: %s\n", reply.c_str());
- return 0;
- }
- namespace {
- // Logic and data behind the server's behavior.
- class GreeterServiceImpl final : public helloworld::Greeter::Service {
- grpc::Status SayHello(grpc::ServerContext* context, const helloworld::HelloRequest* request, helloworld::HelloReply* reply) override {
- std::string prefix("Hello ");
- reply->set_message(prefix + request->name());
- return grpc::Status::OK;
- }
- };
- void RunServer() {
- std::string server_address("0.0.0.0:50051");
- GreeterServiceImpl service;
- grpc::ServerBuilder builder;
- // Listen on the given address without any authentication mechanism.
- builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
- // Register "service" as the instance through which we'll communicate with clients.
- // In this case it corresponds to an *synchronous* service.
- builder.RegisterService(&service);
- // Finally assemble the server.
- std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
- fprintf(stdout, "Server listening on: %s\n", server_address.c_str());
- // Wait for the server to shutdown. Note that some other thread must be
- // responsible for shutting down the server for this call to ever return.
- server->Wait();
- }
- } // namespace
- int test_grpc_server()
- {
- fprintf(stdout, "server start\n");
- RunServer();
- return 0;
- }
4. 先在一个终端启动服务端程序,再在另一个终端启动客户端程序,执行结果如下:
联系客服