gRPC C++简单示例及代码

gRPC安装

https://grpc.io/
编译gRPC的时候官方给的是 make -j并行编译,如果是虚拟机容易出错,建议make
另外,cmake版本和官方文档最好一致,否则容易出奇怪make错误。之前用过Go的gRPC,没想到C++的gRPC会麻烦这么多。

实现效果

server端接受client传来的一个数加一后返回给client。
server端给出了简单RPC和基于stream的RPC。
项目代码:https://github.com/ZYunfeii/SimpleGrpc/blob/master/server.cc

Proto

syntax = "proto3";

package ZYF;
service YServer{
    rpc GetNum(Num) returns (Res) {}
    rpc GetVec(stream Vec)  returns (stream Vec) {}
}

message Num {
    int32 x = 1;
}

message Res {
    int32 y = 1;
}

message Vec {
    repeated int32 v = 1;
}

Server

#include 
#include 
#include 
#include "demo.grpc.pb.h"

class DemoServiceImpl final : public ZYF::YServer::Service {
    // Simple request and response
    grpc::Status GetNum(grpc::ServerContext* context, const ZYF::Num* req, ZYF::Res* res) override {
        std::cout << "Req get:" << req->x() << std::endl;
        res->set_y(req->x() + 1);
        return grpc::Status::OK;
    }
    // Based on stream 
    grpc::Status GetVec(grpc::ServerContext* context, grpc::ServerReaderWriter<ZYF::Vec, ZYF::Vec>* stream) override {
        ZYF::Vec req;
        while (stream->Read(&req)) {
            std::cout << "[stream]: Received message!" << std::endl;
            auto vec = req.v();
            for (auto it = vec.begin(); it != vec.end(); it++) {
                (*it)++;
            }
            stream->Write(req);
        }
        return grpc::Status::OK;
    }
};

void RunServer() {
    std::string serverAddr("0.0.0.0:50051");
    DemoServiceImpl service;
    grpc::ServerBuilder builder;
    builder.AddListeningPort(serverAddr, grpc::InsecureServerCredentials());
    builder.RegisterService(&service);
    std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
    std::cout << "Server listening on:" << serverAddr << std::endl;
    server->Wait();
}

int main(int argc, char** argv) {
    RunServer();
    return 0;
}

Client

#include 
#include 
#include 
#include "demo.grpc.pb.h"

class Client {
public:
    Client(std::shared_ptr<grpc::Channel> channel):stub_(ZYF::YServer::NewStub(channel)){}
    int SendRequest() {
        ZYF::Num req;
        req.set_x(3);
        ZYF::Res res;
        grpc::ClientContext context;
        grpc::Status status = stub_->GetNum(&context, req, &res);

        if (!status.ok()) {
            return -1;
        }
        return res.y();
    }
    // Send requests based on gRPC stream
    void SendRequestStream() {
        grpc::ClientContext context;
        std::shared_ptr<grpc::ClientReaderWriter<ZYF::Vec, ZYF::Vec>> stream(stub_->GetVec(&context));
        for (int i = 0; i < 5; ++i) {
            ZYF::Vec req;
            for (int j = 0; j < 10; ++j) {
                req.add_v(j);
            }
            if (!stream->Write(req)) {
                std::cout << "The stream has been closed!" << std::endl;
                break;
            }
            std::cout << "Send a message based on stream!" << std::endl;
        }
        stream->WritesDone();

        ZYF::Vec res;
        while (stream->Read(&res)) {
            std::cout << "Receive a reply!" << std::endl;
            auto reply = res.v();
            for (auto it = reply.begin(); it != reply.end(); it++) {
                std::cout << (*it) << " " << std::endl;
            }
            std::cout << std::endl;
        }
        stream->Finish();
    }
private:
    std::unique_ptr<ZYF::YServer::Stub> stub_;
};

int main(int argc, char** argv) {
    Client client(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));
    std::cout << "Got Response:" << client.SendRequest() << std::endl;
    client.SendRequestStream();
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.5.1)

project(DemoGrpc C CXX)
include(./common.cmake)

set(proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/../demo.pb.cc")
set(proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../demo.pb.h")
set(grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/../demo.grpc.pb.cc")
set(grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../demo.grpc.pb.h")

include_directories("${CMAKE_CURRENT_BINARY_DIR}")

add_library(grpc_proto ${proto_srcs} ${proto_hdrs} ${grpc_srcs} ${grpc_hdrs})

target_link_libraries(grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF})

add_executable(demoServer "server.cc")
add_executable(demoClient "client.cc")
target_link_libraries(demoServer grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF})
target_link_libraries(demoClient grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF})

你可能感兴趣的:(C++,Linux,计算机网络,c++,开发语言)