gRPC(gRPC Remote Procedure Calls)是一种现代远程过程调用(RPC)框架,支持客户端与服务器应用之间的高效通信。它采用 HTTP/2 作为传输协议,并以 Protocol Buffers 作为接口描述语言(IDL)。在 C++ gRPC 的语境下,该框架可实现 C++ 与其他编程语言开发的系统之间的无缝交互。
将 gRPC 与 C++ 结合使用具有多种优势:
以下是如何在Windows上安装gRPC和Protocol Buffers(macOS和Linux也适用类似的步骤):
# git clone https://github.com/grpc/grpc.git
# cd grpc
# git submodule update --init
git clone --recurse-submodules -b v1.71.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc
这里需要根据需要切换分支,这里使用v1.71.0分支
cd grpc
mkdir -p cmake/build
cd cmake/build
cmake -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DCMAKE_CXX_STANDARD=17 -DCMAKE_INSTALL_PREFIX="./install" ..\..
cmake --build . --config Release --target install -j 4
gRPC基于客户端-服务器架构,围绕以下核心概念构建:
│ CMakeLists.txt
├─client
│ CMakeLists.txt
│ main.cpp
├─protocol
│ CMakeLists.txt
│ helloworld.proto
└─server
CMakeLists.txt
main.cpp
顶级cmake文件如下:
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(grpc_example)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_subdirectory(protocol)
add_subdirectory(server)
add_subdirectory(client)
创建一个叫protocol的目录,并创建文件CMakeLists.txt和helloworld.proto,内容如下:
helloworld.proto
syntax = "proto3";
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;
}
CMakeLists.txt
set(CMAKE_PREFIX_PATH "E:/Code/Net/grpc/cmake/build/install")
# 查找依赖
find_package(Protobuf REQUIRED CONFIG)
find_package(gRPC REQUIRED CONFIG)
if (Protobuf_FOUND)
message(STATUS "Protobuf include dir: ${Protobuf_INCLUDE_DIRS}")
message(STATUS "Protobuf library: ${Protobuf_LIBRARY}")
message(STATUS "Protobuf version: ${Protobuf_VERSION}")
else()
message(FATAL_ERROR "Protobuf not found")
endif()
if (gRPC_FOUND)
message(STATUS "gRPC include dir: ${gRPC_INCLUDE_DIRS}")
message(STATUS "gRPC library: ${gRPC_LIBRARY}")
message(STATUS "gRPC version: ${gRPC_VERSION}")
else()
message(FATAL_ERROR "gRPC not found")
endif()
file(GLOB PROTO_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.proto")
add_library(protocol ${PROTO_FILES})
target_link_libraries(protocol
PUBLIC
protobuf::libprotobuf
gRPC::grpc
gRPC::grpc++
)
target_include_directories(protocol PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
# 生成代码
get_target_property(grpc_cpp_plugin_location gRPC::grpc_cpp_plugin LOCATION)
protobuf_generate(TARGET protocol LANGUAGE cpp)
protobuf_generate(TARGET protocol LANGUAGE grpc GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=${grpc_cpp_plugin_location}")
#include
#include "helloworld.grpc.pb.h"
int main()
{
auto channel = grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials());
std::unique_ptr<helloworld::Greeter::Stub> stub = helloworld::Greeter::NewStub(channel);
helloworld::HelloRequest request;
request.set_name("World");
helloworld::HelloReply reply;
grpc::ClientContext context;
grpc::Status status = stub->SayHello(&context, request, &reply);
if (status.ok())
{
std::cout << "Response: " << reply.message() << std::endl;
}
else
{
std::cout << "RPC failed" << std::endl;
}
return 0;
}
CMakelists.txt
find_package(Threads REQUIRED)
# 创建可执行文件
add_executable(client main.cpp)
# 链接库文件
target_link_libraries(client
PRIVATE
protocol
)
#include
#include "helloworld.grpc.pb.h"
class GreeterServiceImpl final : public helloworld::Greeter::Service
{
grpc::Status SayHello(grpc::ServerContext *context,
const helloworld::HelloRequest *request,
helloworld::HelloReply *reply) override
{
reply->set_message("Hello " + request->name());
return grpc::Status::OK;
}
};
int main()
{
GreeterServiceImpl service;
grpc::ServerBuilder builder;
builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
server->Wait();
return 0;
}
CMakelists.txt
find_package(Threads REQUIRED)
# 创建可执行文件
add_executable(server main.cpp)
# 链接库文件
target_link_libraries(server
PRIVATE
protocol
)
mkdir build
cd build
cmake ..
cmake --build . --parallel
# 等效简写形式:cmake --build . -j 4
cmake --build . --parallel 4