LoginSignup
1
1

More than 1 year has passed since last update.

C++ を用いて grpc を実装したい人生だった。【サーバサイドの実装】

Last updated at Posted at 2022-02-15

@kenmaroです。
普段は主に秘密計算、準同型暗号などの記事について投稿しています
秘密計算に関連するまとめの記事に関しては以下をご覧ください。

概要

grpcをC++を用いて実装するときの、公式チュートリアル

を終えた後に行うと理解が深まるチュートリアル

として書いています。

今回のチュートリアルの構成

以下の流れで記事を分けて書いており、この記事は第二回の内容となります。

準備

前回も使用したチュートリアルレポジトリを使います。

今回は、使用ブランチを step2
として下さい。クローンした後にブランチを移動する場合、

git checkout -b step2 origin/step2

として下さい。

前回とのレポジトリの変更点は

controller/myserver.cpp

のみとなります。

サーバサイドの実装

controller/myserver.cpp
をみて下さい。

後半部分の void RunServer(){}
関数以下は基本的にはテンプレとなります。

controller/myserver.cpp
void RunServer() {
  std::string server_address("0.0.0.0:5001");
  MyServerServiceImpl service;

  grpc::EnableDefaultHealthCheckService(true);
  grpc::reflection::InitProtoReflectionServerBuilderPlugin();
  ServerBuilder builder;
  // Listen on the given address without any authentication mechanism.
  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
  builder.SetMaxReceiveMessageSize(2000000000);
  builder.SetSyncServerOption(ServerBuilder::SyncServerOption::NUM_CQS, 1);
  builder.SetSyncServerOption(ServerBuilder::SyncServerOption::MIN_POLLERS, 3);
  builder.SetSyncServerOption(ServerBuilder::SyncServerOption::MAX_POLLERS, 4);
  builder.SetSyncServerOption(ServerBuilder::SyncServerOption::CQ_TIMEOUT_MSEC, 10000);
  // 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) {
  printf("hello, world\n");
  RunServer();
  return 0;
}

前半部分の、

class MyServerServiceImpl final : public MyServer::Service

にて実際の関数の中身を書いていくことになります。

今回は、各関数はプリントを行うだけで何もしない関数として定義しています。

第四回にて、実際にクライアントサイドからデータを受け取り、実際の操作を行った上でクライアント側に結果を渡すようなコードを実装しようと思います。

controller/myserver.cpp
  Status test1(ServerContext* context, const PB_Message* request, PB_Message* reply) override {
    printf("[ServerService: test1] called.\n");


    printf("[ServerService: test1] done.\n");

    return Status::OK;
  }

  Status test2(ServerContext* context, const PB_DoubleList* request, PB_DoubleList* reply) override {
    printf("[ServerService: test2] called.\n");


    printf("[ServerService: test2] done.\n");

    return Status::OK;
  }

  Status test3(ServerContext* context, const PB_Data* request, PB_Data* reply) override {
    printf("[ServerService: test3] called.\n");


    printf("[ServerService: test3] done.\n");

    return Status::OK;
  }

基本的に、各関数の引数は、context, 入力となるprotobuf, 出力となるprotobuf
となります。

実行

pushd proto
sh proto.sh
popd
mkdir build
cd build
cmake ..
make -j4

でビルドしたら、

./myserver

でサーバを起動します。

root@8233ca8d11d9:/grpc_cpp/build# ./myserver
hello, world
Server listening on 0.0.0.0:5001

となり、サーバが起動し待機状態になるはずです。

まとめ

C++ で実装するgrpc についての記事があまり充実していなかった(気がした)ため、
今回は私が知っているgrpcについての知識を全て書いていくべく、
数回にわけてチュートリアル(公式のチュートリアルの次に行いたいこと)をまとめて行っています。

今回は第二回として、サーバサイドを簡易的に実装しました。

誰かの役に立てれば幸いです。

次回も是非ご覧ください。

今回はこの辺で。

@kenmaro

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1