クイックスタート

このガイドでは、簡単な動作例を用いて、C++でgRPCを使い始める方法を説明します。

クイックスタート

このガイドでは、簡単な動作例を用いて、C++でgRPCを使い始める方法を説明します。

C++の世界では、プロジェクトの依存関係を管理するための普遍的に受け入れられている標準はありません。このクイックスタートのHello Worldの例をビルドして実行する前に、gRPCをビルドしてインストールする必要があります。

gRPCとProtocol Buffersをビルドし、ローカルにインストールする

このセクションの手順では、cmakeを使用してgRPCとProtocol Buffersをビルドし、ローカルにインストールする方法を説明します。代わりにbazelを使用したい場合は、ソースからビルドを参照してください。

セットアップ

ローカルにインストールされたパッケージを保持するディレクトリを選択します。このページでは、環境変数MY_INSTALL_DIRがこのディレクトリのパスを保持していることを前提としています。例えば

$ export MY_INSTALL_DIR=$HOME/.local

ディレクトリが存在することを確認してください

$ mkdir -p $MY_INSTALL_DIR

ローカルのbinフォルダをパス変数に追加します。例えば

$ export PATH="$MY_INSTALL_DIR/bin:$PATH"

cmakeをインストールする

cmakeのバージョン3.13以降が必要です。次の手順に従ってインストールしてください

  • Linux

    $ sudo apt install -y cmake
    
  • macOS

    $ brew install cmake
    
  • cmakeの一般的なインストール手順については、CMakeのインストールを参照してください。

cmakeのバージョンを確認してください

$ cmake --version
cmake version 3.19.6

Linuxでは、システム全体のcmakeのバージョンが古すぎる場合があります。次の方法で、より新しいバージョンをローカルインストールディレクトリにインストールできます

$ wget -q -O cmake-linux.sh https://github.com/Kitware/CMake/releases/download/v3.19.6/cmake-3.19.6-Linux-x86_64.sh
$ sh cmake-linux.sh -- --skip-license --prefix=$MY_INSTALL_DIR
$ rm cmake-linux.sh

その他の必要なツールをインストールする

gRPCをビルドするために必要な基本ツールをインストールします

  • Linux

    $ sudo apt install -y build-essential autoconf libtool pkg-config
    
  • macOS

    $ brew install autoconf automake libtool pkg-config
    

grpcリポジトリをクローンする

grpcリポジトリとそのサブモジュールをクローンします

$ git clone --recurse-submodules -b v1.62.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc

gRPCとProtocol Buffersをビルドしてインストールする

必須ではありませんが、gRPCアプリケーションは通常、サービス定義とデータシリアライゼーションのためにProtocol Buffersを利用し、例のコードではproto3を使用します。

次のコマンドは、gRPCとProtocol Buffersをビルドしてローカルにインストールします

$ cd grpc
$ mkdir -p cmake/build
$ pushd cmake/build
$ cmake -DgRPC_INSTALL=ON \
      -DgRPC_BUILD_TESTS=OFF \
      -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR \
      ../..
$ make -j 4
$ make install
$ popd

詳細

例をビルドする

例のコードは、前のセクションの手順の一部としてクローンしたgrpcリポジトリのソースの一部です。

  1. 例のディレクトリに移動します

    $ cd examples/cpp/helloworld
    
  2. cmakeを使用して例をビルドします

    $ mkdir -p cmake/build
    $ pushd cmake/build
    $ cmake -DCMAKE_PREFIX_PATH=$MY_INSTALL_DIR ../..
    $ make -j 4
    

試してみよう!

例のビルドディレクトリexamples/cpp/helloworld/cmake/buildから例を実行します

  1. サーバーを実行します

    $ ./greeter_server
    
  2. 別のターミナルから、クライアントを実行してクライアントの出力を確認します

    $ ./greeter_client
    Greeter received: Hello world
    

おめでとうございます!gRPCを使用してクライアント/サーバーアプリケーションを実行しました。

gRPCサービスを更新する

次に、クライアントが呼び出すための追加のメソッドをサーバーでアプリケーションを更新する方法を見てみましょう。gRPCサービスは、プロトコルバッファーを使用して定義されます。.protoファイルでサービスを定義する方法については、gRPCの概要基本チュートリアルで詳しく知ることができます。今のところ知っておく必要があるのは、サーバーとクライアントスタブの両方に、クライアントからのHelloRequestパラメータを受け取り、サーバーからのHelloReplyを返すSayHello()RPCメソッドがあること、そしてこのメソッドがこのように定義されているということです

// 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;
}

examples/protos/helloworld.protoを開き、同じリクエストタイプとレスポンスタイプを使用して、新しいSayHelloAgain()メソッドを追加します

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  // Sends another greeting
  rpc SayHelloAgain (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;
}

ファイルを保存することを忘れないでください!

gRPCコードを再生成する

新しいサービスメソッドを使用する前に、更新されたprotoファイルを再コンパイルする必要があります。

例のビルドディレクトリexamples/cpp/helloworld/cmake/buildから、実行します

$ make -j 4

これにより、生成されたクライアントクラスとサーバークラス、およびリクエストタイプとレスポンスタイプを入力、シリアライズ、および取得するためのクラスを含むhelloworld.pb.{h,cc}helloworld.grpc.pb.{h,cc}が再生成されます。

アプリケーションを更新して実行する

新しい生成されたサーバーコードとクライアントコードがありますが、例のアプリケーションの人間が書いた部分で新しいメソッドを実装して呼び出す必要があります。

サーバーを更新する

例のルートディレクトリからgreeter_server.ccを開きます。次のように新しいメソッドを実装します

class GreeterServiceImpl final : public Greeter::Service {
  Status SayHello(ServerContext* context, const HelloRequest* request,
                  HelloReply* reply) override {
     // ...
  }

  Status SayHelloAgain(ServerContext* context, const HelloRequest* request,
                       HelloReply* reply) override {
    std::string prefix("Hello again ");
    reply->set_message(prefix + request->name());
    return Status::OK;
  }
};

クライアントを更新する

新しいSayHelloAgain()メソッドがスタブで使用可能になりました。すでに存在するSayHello()と同じパターンに従い、新しいSayHelloAgain()メソッドをGreeterClientに追加します

class GreeterClient {
 public:
  // ...
  std::string SayHello(const std::string& user) {
     // ...
  }

  std::string SayHelloAgain(const std::string& user) {
    // Follows the same pattern as SayHello.
    HelloRequest request;
    request.set_name(user);
    HelloReply reply;
    ClientContext context;

    // Here we can use the stub's newly available method we just added.
    Status status = stub_->SayHelloAgain(&context, request, &reply);
    if (status.ok()) {
      return reply.message();
    } else {
      std::cout << status.error_code() << ": " << status.error_message()
                << std::endl;
      return "RPC failed";
    }
  }

最後に、main()でこの新しいメソッドを呼び出します

int main(int argc, char** argv) {
  // ...
  std::string reply = greeter.SayHello(user);
  std::cout << "Greeter received: " << reply << std::endl;

  reply = greeter.SayHelloAgain(user);
  std::cout << "Greeter received: " << reply << std::endl;

  return 0;
}

実行!

以前と同じようにクライアントとサーバーを実行します。例のビルドディレクトリexamples/cpp/helloworld/cmake/buildから次のコマンドを実行します

  1. 変更を加えた後、クライアントとサーバーをビルドします

    $ make -j 4
    
  2. サーバーを実行します

    $ ./greeter_server
    
  3. 別のターミナルで、クライアントを実行します

    $ ./greeter_client
    

    次の出力が表示されます

    Greeter received: Hello world
    Greeter received: Hello again world
    

次のステップ