• 在 c++ 项目中使用 grpc —— 有管理员权限


    注1:参考代码取自 grpc 源码目录下的 examples\cpp\helloworld

    注2:操作系统 Ubuntu 16.04

    1. 安装 protoc 工具

    • 下载 Grpc_v1.43.0_SetupFile.zip 文件,解压到任意目录
      下载链接:https://pan.baidu.com/s/1HYjfQb8CQY56QF2iAGmBNw 
      提取码:grg0
      注:Grpc_v1.43.0_SetupFile.zip 可由 grpc 源码编译安装得到,编译比较吃电脑配置,直接下载编译好的文件即可。

    • 将解压后的 Grpc_v1.43.0_SetupFile/bin 中 的 protoc(文本文件,记录了版本信息)重命名为 protoc.version,然后将 protoc-3.18.1.0(可执行程序)拷贝一下并重命名为 protoc
      注:原 protoc-3.18.1.0 文件也是需要用的,不能直接重命名。

    •  在 Grpc_v1.43.0_SetupFile 目录打开终端,执行命令如下:
      chmod +x bin/*
      sudo cp -r . /usr/local/
       

    2. 通过 protoc 生成 c++ 代码

    • 任意目录下新建空文件夹 grpc_cpp_demo,在文件夹中创建 helloworld.proto 文件,示例如下:
      // Copyright 2015 gRPC authors.
      //
      // Licensed under the Apache License, Version 2.0 (the "License");
      // you may not use this file except in compliance with the License.
      // You may obtain a copy of the License at
      //
      //     http://www.apache.org/licenses/LICENSE-2.0
      //
      // Unless required by applicable law or agreed to in writing, software
      // distributed under the License is distributed on an "AS IS" BASIS,
      // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      // See the License for the specific language governing permissions and
      // limitations under the License.
      
      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;
      }
      View Code
    • 生成 Protobuf 消息 和 grpc 客户端和服务器
      在 grpc_cpp_demo 目录下打开终端,执行如下命令:
      protoc --cpp_out=./ helloworld.proto
      protoc --grpc_out=./ --plugin=protoc-gen-grpc=/usr/local/bin/grpc_cpp_plugin helloworld.proto

    3. 编写客户端/服务器实现自定义业务逻辑

    • 在 目录 grpc_cpp_demo 下,新建文件 greeter_server.cc 来编写服务器端相关代码,示例文件如下:
      /*
       *
       * Copyright 2015 gRPC authors.
       *
       * Licensed under the Apache License, Version 2.0 (the "License");
       * you may not use this file except in compliance with the License.
       * You may obtain a copy of the License at
       *
       *     http://www.apache.org/licenses/LICENSE-2.0
       *
       * Unless required by applicable law or agreed to in writing, software
       * distributed under the License is distributed on an "AS IS" BASIS,
       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       * See the License for the specific language governing permissions and
       * limitations under the License.
       *
       */
      
      #include <iostream>
      #include <memory>
      #include <string>
      
      #include <grpcpp/grpcpp.h>
      #include <grpcpp/health_check_service_interface.h>
      #include <grpcpp/ext/proto_server_reflection_plugin.h>
      
      #ifdef BAZEL_BUILD
      #include "examples/protos/helloworld.grpc.pb.h"
      #else
      #include "helloworld.grpc.pb.h"
      #endif
      
      using grpc::Server;
      using grpc::ServerBuilder;
      using grpc::ServerContext;
      using grpc::Status;
      using helloworld::HelloRequest;
      using helloworld::HelloReply;
      using helloworld::Greeter;
      
      // Logic and data behind the server's behavior.
      class GreeterServiceImpl final : public Greeter::Service {
        Status SayHello(ServerContext* context, const HelloRequest* request,
                        HelloReply* reply) override {
          std::string prefix("Hello ");
          reply->set_message(prefix + request->name());
          return Status::OK;
        }
      };
      
      void RunServer() {
        std::string server_address("0.0.0.0:50051");
        GreeterServiceImpl service;
      
        grpc::EnableDefaultHealthCheckService(true);
        grpc::reflection::InitProtoReflectionServerBuilderPlugin();
        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<Server> server(builder.BuildAndStart());
        std::cout << "Server listening on " << server_address << std::endl;
      
        // 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();
      }
      
      int main(int argc, char** argv) {
        RunServer();
      
        return 0;
      }
      View Code
    • 在 目录 grpc_cpp_demo 下,新建文件 greeter_client.cc 来编写客户端相关代码,示例文件如下:
      /*
       *
       * Copyright 2015 gRPC authors.
       *
       * Licensed under the Apache License, Version 2.0 (the "License");
       * you may not use this file except in compliance with the License.
       * You may obtain a copy of the License at
       *
       *     http://www.apache.org/licenses/LICENSE-2.0
       *
       * Unless required by applicable law or agreed to in writing, software
       * distributed under the License is distributed on an "AS IS" BASIS,
       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       * See the License for the specific language governing permissions and
       * limitations under the License.
       *
       */
      
      #include <iostream>
      #include <memory>
      #include <string>
      
      #include <grpcpp/grpcpp.h>
      
      #ifdef BAZEL_BUILD
      #include "examples/protos/helloworld.grpc.pb.h"
      #else
      #include "helloworld.grpc.pb.h"
      #endif
      
      using grpc::Channel;
      using grpc::ClientContext;
      using grpc::Status;
      using helloworld::HelloRequest;
      using helloworld::HelloReply;
      using helloworld::Greeter;
      
      class GreeterClient {
       public:
        GreeterClient(std::shared_ptr<Channel> channel)
            : stub_(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.
          HelloRequest request;
          request.set_name(user);
      
          // Container for the data we expect from the server.
          HelloReply reply;
      
          // Context for the client. It could be used to convey extra information to
          // the server and/or tweak certain RPC behaviors.
          ClientContext context;
      
          // The actual RPC.
          Status status = stub_->SayHello(&context, request, &reply);
      
          // Act upon its status.
          if (status.ok()) {
            return reply.message();
          } else {
            std::cout << status.error_code() << ": " << status.error_message()
                      << std::endl;
            return "RPC failed";
          }
        }
      
       private:
        std::unique_ptr<Greeter::Stub> stub_;
      };
      
      int main(int argc, char** argv) {
        // Instantiate the client. It requires a channel, out of which the actual RPCs
        // are created. This channel models a connection to an endpoint specified by
        // the argument "--target=" which is the only expected argument.
        // We indicate that the channel isn't authenticated (use of
        // InsecureChannelCredentials()).
        std::string target_str;
        std::string arg_str("--target");
        if (argc > 1) {
          std::string arg_val = argv[1];
          size_t start_pos = arg_val.find(arg_str);
          if (start_pos != std::string::npos) {
            start_pos += arg_str.size();
            if (arg_val[start_pos] == '=') {
              target_str = arg_val.substr(start_pos + 1);
            } else {
              std::cout << "The only correct argument syntax is --target=" << std::endl;
              return 0;
            }
          } else {
            std::cout << "The only acceptable argument is --target=" << std::endl;
            return 0;
          }
        } else {
          target_str = "localhost:50051";
        }
        GreeterClient greeter(grpc::CreateChannel(
            target_str, grpc::InsecureChannelCredentials()));
        std::string user("world");
        std::string reply = greeter.SayHello(user);
        std::cout << "Greeter received: " << reply << std::endl;
      
        return 0;
      }
      View Code

        

    4. 通过 CMake 编译项目

    • 在 目录 grpc_cpp_demo 下,新建文件 CMakeLists.txt 来编写 CMake 编译指令,示例文件如下:
      cmake_minimum_required(VERSION 3.5)
      
      project(grpc_cpp_demo LANGUAGES CXX)
      
      set(CMAKE_CXX_STANDARD 11)
      set(CMAKE_CXX_STANDARD_REQUIRED ON)
      
      #添加 Protobuf 和 gRPC 三方库
      find_package(Threads REQUIRED)
      find_package(Protobuf CONFIG REQUIRED)
      find_package(gRPC CONFIG REQUIRED)
      
      set(_GRPC_GRPCPP gRPC::grpc++)
      set(_GRPC_REFLECTION gRPC::grpc++_reflection)
      set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
      
      message(STATUS "Using gRPC ${gRPC_VERSION}")
      message(STATUS "Using protobuf ${Protobuf_VERSION}")
      
      #生成可执行文件
      foreach(_target greeter_client greeter_server)
         add_executable(${_target}
            ${_target}.cc
            helloworld.grpc.pb.cc
            helloworld.grpc.pb.h
            helloworld.pb.cc
            helloworld.pb.h)
      
         target_link_libraries(${_target}    
            ${_GRPC_GRPCPP}
            ${_GRPC_REFLECTION}
            ${_PROTOBUF_LIBPROTOBUF})
      endforeach()
      View Code
    • 在目录 grpc_cpp_demo 下,打开终端,执行如下命令:
      mkdir -p cmake/build
      pushd cmake/build
      cmake  ../..
      make -j
      popd

    5. 运行项目

    • 在目录 grpc_cpp_demo/cmake/build 打开 2 个终端,分别运行如下命令
      ./greeter_server
      ./greeter_client 
    • 终端输出如下:
      Server listening on 0.0.0.0:50051
      Greeter received: Hello world

      

  • 相关阅读:
    HTTP协议
    安全测试-渗透性测试
    网络安全、Web安全、渗透测试之笔经面经总结(三)
    Struts2拦截器再认识
    struts2.5+框架使用通配符与动态方法
    struts.xml配置详解
    代理概述
    Mybatis Plugin(拦截器)的开发
    详解环境搭建SSM
    mybatis-databaseIdProvider多数据库支持
  • 原文地址:https://www.cnblogs.com/dhqy/p/15882297.html
Copyright © 2020-2023  润新知