grpc demo python客户端 c++服务端
项目需啊将网站上传的图片传入c++推理引擎,网站使用flask架构,python编写,图片推理引擎是一个单独的server,c++编写,因此用grpc来传输比较合适。理论上来说只要规定好proto文件,即使语言不通也是可以实现客户端和服务端的交互的。下面是一个简单的demo,结构如下。
![](https://img2022.cnblogs.com/blog/901097/202210/901097-20221031155014699-961488905.png)
客户端和服务端的proto文件是一致的,其实最好就用一个文件,把它放在上级目录中,这里图方便就复制了一份,下面是test.proto
syntax = "proto3"; option java_multiple_files = true; option java_package = "io.grpc.example.test"; option java_outer_classname = "TestProto"; option objc_class_prefix = "HLW"; package test; message Data { int32 data = 1; } message ReplyMsg { string message = 1; } service CommunicationTest { rpc getData(Data) returns (ReplyMsg) {} }
c++ server生成grpc代码的脚本
# mkdir gen_code /usr/local/bin/protoc --version /usr/local/bin/protoc -I ./ --grpc_out=./gen_code --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ./test.proto /usr/local/bin/protoc -I ./ --cpp_out=./gen_code ./test.proto
python client生成grpc代码的脚本
python -m grpc_tools.protoc -I ./ --python_out=./gen_code --grpc_python_out=./gen_code ./test.proto
c++ server端代码
#include <grpc/grpc.h> #include <grpcpp/security/server_credentials.h> #include <grpcpp/server.h> #include <grpcpp/server_builder.h> #include <grpcpp/server_context.h> #include <iostream> #include <string> #include <memory> #include "./gen_code/test.grpc.pb.h" using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::ServerReader; using grpc::ServerReaderWriter; using grpc::ServerWriter; using grpc::Status; class TestImpl final : public test::CommunicationTest::Service { public: grpc::Status getData(grpc::ServerContext *context, const test::Data *data, test::ReplyMsg *msg) override { std::cout << "grpc get data: " << data->data() << std::endl; std::string tmp("data received successful, this is reply message"); msg->set_message(tmp); return grpc::Status::OK; } }; void RunServer() { TestImpl service; grpc::ServerBuilder builder; builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr<grpc::Server> server(builder.BuildAndStart()); std::cout << "Server listening on 0.0.0.0:50051" << std::endl; server->Wait(); } int main(int argc, char **argv) { RunServer(); return 0; }
CMakeLists.txt
cmake_minimum_required(VERSION 3.5) project(test) find_package(Threads REQUIRED) find_package(Protobuf CONFIG REQUIRED) set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>) set(_REFLECTION gRPC::grpc++_reflection) find_package(gRPC REQUIRED) set(_GRPC_GRPCPP gRPC::grpc++) # proto file get_filename_component(test_proto "../test.proto" ABSOLUTE) get_filename_component(test_proto_path "${test_proto}" PATH) # generated sources include_directories("${CMAKE_CURRENT_BINARY_DIR}/../gen_code") set(test_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/../gen_code/test.pb.cc") set(test_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../gen_code/test.pb.h") set(test_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/../gen_code/test.grpc.pb.cc") set(test_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../gen_code/test.grpc.pb.h") # hw_grpc_proto add_library(hw_grpc_proto ${test_grpc_srcs} ${test_grpc_hdrs} ${test_proto_srcs} ${test_proto_hdrs}) target_link_libraries(hw_grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF}) foreach(_target test_server test_client ) add_executable(${_target} "${_target}.cc") target_link_libraries(${_target} hw_grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF}) endforeach()
python client代码
from __future__ import print_function import logging import grpc from gen_code import test_pb2, test_pb2_grpc def run(): print("Will try python grpc test") input_data = input("input message: ") with grpc.insecure_channel('localhost:50051') as channel: stub = test_pb2_grpc.CommunicationTestStub(channel) response = stub.getData(test_pb2.Data(data=int(input_data))) print("test client received: "+ response.message) if __name__ == '__main__': logging.basicConfig() run()
结果如图
无情的摸鱼机器