简介
gRPC是一种由Google推出的RPC框架,开源,跨语言,跨平台,高性能。
gRPC次要是基于protobuf设计实现的。
本文次要介绍如何在C++中应用gRPC。
装置
不像Java,配置一个maven插件,增加相应的maven依赖,就能够搭建好gRPC环境。
C++个别须要下载gRPC的源码,而后编译构建,失去须要的库文件,protoc编译器,以及gRPC插件。
- 下载源码
git clone --recurse-submodules -b v1.41.0 https://github.com/grpc/grpccd grpc
- 创立cmake构建目录
mkdir -p cmake/buildcd cmake/build
- 生成makefile
cmake -DgRPC_INSTALL=ON \ -DgRPC_BUILD_TESTS=OFF \ -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR \ ../..
MY_INSTALL_DIR变量指定了最终生成的库文件,protoc的装置地位,linux零碎个别为/usr/local
- 构建
make -j
- 装置
make install
此命令会依据第三部指定的MY_INSTALL_DIR的,将构建进去的库装置到相应的地位。比方protoc就放在${MY_INSTALL_DIR}/bin目录下,
头文件就放在${MY_INSTALL_DIR}/include/grpc目录下。
当然,执行上述命令须要装置g++, cmake, git等工具。
HelloWorld
应用gRPC首先须要写proto文件,形容rpc,供客户端和服务端应用。
- proto文件接口定义
hello.proto
// protobuf版本syntax = "proto3";// rpc申请的定义message HelloRequest { optional string name = 1;}// rpc响应的定义message HelloReply { optional string message = 1;}// rpc服务的定义,两个函数service HelloWorld { rpc SayHello (HelloRequest) returns (HelloReply) {} rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}}
- 服务端
proto仅定义了接口,还须要在服务端写程序,实现rpc。server.cc
#include "hello.grpc.pb.h"#include <string>#include <grpcpp/grpcpp.h>// rpc服务实现class HelloServiceImpl : public HelloWorld::Service{ grpc::Status SayHello(grpc::ServerContext* context, const HelloRequest* req, HelloReply* rsp) { std::cout << "Request SayHello From " << context->peer() << std::endl; rsp->set_message("hello " + req->name() + "!"); return grpc::Status::OK; } grpc::Status SayHelloAgain(grpc::ServerContext* context, const HelloRequest* req, HelloReply* rsp) { std::cout << "Request SayHelloAgain From " << context->peer() << std::endl; rsp->set_message("hello " + req->name() + " again!!"); return grpc::Status::OK; }};// 启动运行int main(int argc, char** argv){ std::string address("localhost:5000"); HelloServiceImpl service; grpc::ServerBuilder builder; builder.AddListeningPort(address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr<grpc::Server> server(builder.BuildAndStart()); std::cout << "Server Listening on port: " << address << std::endl; server->Wait(); return 0;}
- 客户端
客户端调用服务端的,client.cc
#include "hello.grpc.pb.h"#include <string>#include <iostream>#include <sstream>#include <grpcpp/grpcpp.h>// 客户端class HelloClient{public: HelloClient(std::shared_ptr<grpc::Channel> channel) : _stub(HelloWorld::NewStub(channel)) {} std::string SayHello(const std::string& name) { HelloRequest req; HelloReply rsp; req.set_name(name); grpc::ClientContext context; grpc::Status status = _stub->SayHello(&context, req, &rsp); if(status.ok()) { return rsp.message(); } else { std::ostringstream out; out << status.error_code() << " : " << status.error_message(); return out.str(); } } std::string SayHelloAgain(const std::string& name) { HelloRequest req; HelloReply rsp; req.set_name(name); grpc::ClientContext context; grpc::Status status = _stub->SayHelloAgain(&context, req, &rsp); if(status.ok()) { return rsp.message(); } else { std::ostringstream out; out << status.error_code() << " : " << status.error_message(); return out.str(); } }private: std::unique_ptr<HelloWorld::Stub> _stub;};// 调用rpcint main(int argc, char** argv){ std::string address("0.0.0.0:5000"); HelloClient client(grpc::CreateChannel(address, grpc::InsecureChannelCredentials())); std::string name("bazel"); std::cout << client.SayHello(name) << std::endl; std::cout << client.SayHelloAgain(name) << std::endl; return 0;}
编译运行
- proto编译
protoc --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` hello.proto
上述命令会生成hello.pb.h/cc和hello.grpc.pb.h/cc
- 服务端
g++ -std=c++11 \ `pkg-config --cflags protobuf grpc` \ `pkg-config --libs protobuf grpc++` \ -framework CoreFoundation \ // 仅MacOS须要加 -o server \ hello.pb.cc hello.grpc.pb.cc server.cc
其中pkg-config --cflags protobuf grpc
指定了头文件的地位,pkg-config --libs protobuf grpc++
指定了库文件的地位,-framework CoreFoundation
仅在MacOS中须要增加,这是因为grpc的abseil的time库在MacOS下用的是CoreFoundation中的
而后./server运行
- 客户端
g++ -std=c++11 \ `pkg-config --cflags protobuf grpc` \ `pkg-config --libs protobuf grpc++` -framework CoreFoundation \ // 仅MacOS须要加 -o client \ hello.pb.cc hello.grpc.pb.cc client.cc
而后./client运行
参考
Quick start | C++ | gRPC
gRPC C++ 入门教程