VS2015 编译和使用 gRPC

说明

本例的环境为:WIN10 + VS2015
gRPC 的版本为: 1.4.2
protobuf 的版本为: 3.3.2

准备工作

  1. 本例使用 VS2015 进行编译,其他版本的 VS 没有试过,不过大致步骤应该差不多。
  2. 确保环境变量 PATH 包含 git.exe 所在目录,因为我们要通过 git 下载 gRPC 源码。
  3. 下载并安装 Active State Perl。本例下载的是:ActivePerl-5.24.1.2402-MSWin32-x86-64int-401627.exe。安装后打开命令行,输入以下命令验证安装,如果出现版本信息,就说明安装成功了。

    > perl -v
    
    This is perl 5, version 24, subversion 1 (v5.24.1) built for MSWin32-x86-multi-thread-64int
    (with 1 registered patch, see perl -V for more detail)
    
    ...
  4. 下载并安装 Go (注意:你可能需要设置代理来下载)。本例下载的是:go1.8.3.windows-amd64.msi。安装后打开命令行,输入以下命令验证安装,如果出现版本信息,就说明安装成功了。

    > go version
    go version go1.8.3 windows/amd64

下载源码

  1. 打开命令行,新建一个目录专门用来放置 gRPC 的源码,然后进入该目录。本例是在 G 盘下建立的 grpc 目录,大家应该根据实际情况修改。

    > cd G:
    > md grpc & cd grpc
  2. 用 git 下载 gRPC 源码,本例下载的版本是 1.4.2 。

    > git clone -b v1.4.2 https://github.com/grpc/grpc.git grpc_v1.4.2
  3. 下载后可以在源码根目录找到 INSTALL.md,里面详细介绍了编译方法。

  4. 下载源码后,可以在源码根目录下找到 .gitmodules 文件,该文件是 git 用来描述依赖库的,可以看到 gRPC 的依赖库有:protobuf,gflags,googletest,boringssl,cares,zlib。这些依赖库都需要下载到 third_party 目录下。可以执行以下命令下载这些依赖库,也可以跳过这一步,转到第 5 步开始手动下载。

    > git submodule update --init
  5. 进入到 third_party 目录,下面开始下载 gRPC 的依赖库。

    > cd third_party
  6. 下载 protobuf,这里下载的版本是 3.3.2。

    > git clone -b v3.3.2 https://github.com/google/protobuf.git protobuf
  7. 下载 gflags 。

    > git clone https://github.com/gflags/gflags.git gflags
  8. 下载 googletest 。

    > git clone https://github.com/google/googletest.git googletest
  9. 下载 boringssl 。

    > git clone https://github.com/google/boringssl.git boringssl
  10. 下载 cares 。需要注意下载的版本为:cares-1_12_0 。下载的目录为 cares\cares

    > git clone -b cares-1_12_0 https://github.com/c-ares/c-ares.git cares/cares
  11. 下载 zlib 。

    > git clone https://github.com/madler/zlib.git zlib

编译

  1. 找到 third_party\boringssl 目录下的 CMakeLists.txt,用编辑器打开它,搜索 MSVC_DISABLED_WARNINGS_LIST,找到后,在下面添加 "C4819",消除警告:该文件包含不能在当前代码页(数字)中表示的字符。 以 Unicode 格式保存该文件防止数据丢失。

  2. 切换到源码目录,在源码目录下创建一个 .build (如果要编译64位,则是 .build_x64)子目录,我们用该目录保存所有生成的工程文件。创建后进入该目录。

    32位:

    > md .build & cd .build

    64位:

    > md .build_x64 &cd .build_x64
  3. 用 cmake 生成工程文件。生成后可以在 .build (或 .build_x64)目录下看到生成的工程和项目文件。

    32位:

    > cmake .. -G "Visual Studio 14 2015" -DCMAKE_BUILD_TYPE=Release

    64位:

    > cmake .. -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=Release
  4. 使用 MSBuild 编译工程。打开 VS2015 开发人员命令提示符,切换到 .build (或 .build_x64)目录下,执行下面的命令进行编译。

    编译 32 位 Debug 版本:

    > MSBuild ALL_BUILD.vcxproj /t:Build /p:Configuration=Debug;Platform=Win32

    编译 32 位 Release 版本:

    > MSBuild ALL_BUILD.vcxproj /t:Build /p:Configuration=Release;Platform=Win32

    编译 64 位 Debug 版本:

    > MSBuild ALL_BUILD.vcxproj /t:Build /p:Configuration=Debug;Platform=x64

    编译 64 位 Release 版本:

    > MSBuild ALL_BUILD.vcxproj /t:Build /p:Configuration=Release;Platform=x64

    如果遇到如下错误,则用编辑器打开 .build\third_party\boringssl\crypto_test_data.cc ,在第 2604 行最后面的双引号 " 之前加个空格。保存,退出,重新编译。

    G:\grpc\grpc_v1.4.2\.build\third_party\boringssl\crypto_test_data.cc(2604): error C2001: 常量中有换行符

    编译好之后,可以在相应项目目录下的 DebugRelease 子目录中找到我们需要的库和工具。如下所示(仅列出重要部分):

    .build\
      |-Debug\
      |  |-grpc++.lib             -- C++ 的 gRPC 库
      |  |-grpc_cpp_plugin.exe    -- 用来生成 C++ 的 RPC 代码 
      |-third_party\              -- 这里放的是 gRPC 的依赖库
         |-boringssl\
         |  |-crypto\
         |  |  |-Debug\
         |  |     |-crypto.lib
         |  |-ssl\
         |     |-Debug\
         |        |-ssl.lib
         |-cares\
         |  |-Debug\
         |     |-cares.lib
         |-gflags\
         |  |-Debug\
         |  |  |-gflags_nothreads_static.lib
         |-protobuf\
         |  |-Debug\
         |     |-libprotocd.lib   -- protocol buffer 库
         |     |-protoc.exe       -- protocol buffer 编译器
         |-zlib\
            |-Debug\
               |-zlibstaticd.lib

实例

下面写一个小程序测试一下。

新建 [空白解决方案],命名为 Calculator。如下图:


这里写图片描述

创建接口

添加 [Win32 控制台应用程序],命名为 ICalc。如下图:


这里写图片描述

在 [应用程序设置页面],勾选 [空项目]。如下图所示。点击完成。

这里写图片描述

.build\third_party\protobuf\Debug\protoc.exe.build\Debug\grpc_cpp_plugin.exe 拷贝到项目目录中。拷贝后的目录如下所示:

这里写图片描述

新建 [C++ 文件(.cpp)],命名为 calculator.proto。注意一定要带 .proto 后缀,否则的话后缀就变成 .cpp 了。如下图所示:

这里写图片描述

calculator.proto 右键,[属性]。 [项类型] 选择 [自定义生成工具]。点击[应用] 按钮。如下图所示:

这里写图片描述

在 [自定义生成工具] -> [常规] 下,[命令行]填写如下命令:

protoc --cpp_out=. calculator.proto
protoc --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin.exe calculator.proto

[说明] 填写 Performing Protoc Build Tools。[输出] 填写 None。[链接对象] 改为 [否]。 如下图所示:


这里写图片描述

打开 calculator.proto,编写如下代码:

syntax = "proto3";

package calc;

service Caltulator {
    rpc Add(Request) returns (Response) {}
}

message Request {
    int32 a = 1;
    int32 b = 2;
}

message Response {
    int32 sum = 1;
}

编译项目,成功后会在项目目录中生成如下文件:

calculator.pb.h
calculator.pb.cc
calculator.grpc.pb.h
calculator.grpc.pb.cc

其中,calculator.pb.hcalculator.pb.cc 是通过 protoc.exe 编译生成的接口数据类型,在这里就是我们在 calculator.proto 中定义的 RequestResponsecalculator.grpc.pb.hcalculator.grpc.pb.cc 是通过 grpc_cpp_plugin.exe 编译生成的服务器以及存根代码。有了这些文件,就可以开始编写服务器和客户端的代码了。

实现服务器

新建 [Win32 控制台应用程序],命名为 Server。如下图所示:


这里写图片描述

在 [应用程序设置] 页面,勾选 [空项目] 。如下图所示:

这里写图片描述

项目右键,[添加现有项],选择上面生成的那四个接口文件:

这里写图片描述

项目 [属性] -> [C/C++] -> [常规] -> [附加包含目录],加入 gRPC 和 Protocol Buffer 的头文件,如下图所示。注意这里应该换成自己实际的目录。

这里写图片描述

项目 [属性] -> [链接器] -> [常规] -> [附加库目录],添加 gRPC 及其依赖库的目录,如下图所示。注意这里应该换成自己实际的目录。

这里写图片描述

项目 [属性] -> [链接器] -> [输入] -> [附加依赖库],添加 gRPC 及其依赖的库,如下图所示。

这里写图片描述

工程 [属性] -> [C/C++] -> [预处理器] -> [预处理器定义],添加 _WIN32_WINNT=0x600

新建 [C++ 文件(.cpp)],命名为 main.cpp,代码如下:

#include "../ICalc/calculator.grpc.pb.h"

#include "grpc++/grpc++.h"

class CalcualtorService : public calc::Caltulator::Service
{
    // 构造、析构
public:

    // 接口实现
public:
    virtual ::grpc::Status Add(::grpc::ServerContext* context,
        const ::calc::Request* request, ::calc::Response* response) override
    {
        response->set_sum(request->a() + request->b());
        return grpc::Status::OK;
    }
};

int main()
{
    std::string server_address("0.0.0.0:50051");

    CalcualtorService service;

    grpc::ServerBuilder builder;
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
    builder.RegisterService(&service);

    std::unique_ptr<grpc::Server> server(builder.BuildAndStart());

    std::cout << "Server listening on " << server_address << std::endl;

    server->Wait();

    return 0;
}

编译工程。生成 Server.exe

实现客户端

实现客户端的步骤和实现服务器的一样,只是最后的 main.cpp 不一样而已。这里简单列出步骤。

  1. 新建 [Win32 控制台应用程序],命名为 Client
  2. 添加在创建接口那一步生成的四个文件:calculator.pb.h calculator.pb.cc calculator.grpc.pb.h calculator.grpc.pb.cc
  3. 接下来和服务器一样,设置好 [附加包含目录],[附加库目录],[附加依赖库]。
  4. [预处理器定义] 添加 _WIN32_WINNT=0x600
  5. 新建 main.cpp,代码如下:

     #include <memory>
    
     #include "grpc++/grpc++.h"
     #include "../ICalc/calculator.grpc.pb.h"
    
    class Client
    {
    public:
        Client(std::shared_ptr<grpc::Channel> channel)
            : stub_(calc::Caltulator::NewStub(channel)) {}
    
        google::protobuf::int32 Add(google::protobuf::int32 a, google::protobuf::int32 b)
        {
            calc::Request request;
            request.set_a(a);
            request.set_b(b);
    
            calc::Response response;
    
            grpc::ClientContext context;
    
            grpc::Status status = stub_->Add(&context, request, &response);
    
            if (status.ok())
            {
                return response.sum();
            }
            else
            {
                return -1;
            }
        }
    
    private:
        std::unique_ptr<calc::Caltulator::Stub> stub_;
    };
    
    int main()
    {
        Client client(grpc::CreateChannel(
            "localhost:50051", grpc::InsecureChannelCredentials()));
    
        auto result = client.Add(1, 2);
        std::cout << "1 + 2 = " << result << std::endl;
    
        return 0;
    }
  6. 编译工程。生成 Client.exe

测试

先启动 Server.exe,再启动 Client.exe。结果如下:


这里写图片描述

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值