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

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

> - [最先端の秘密計算技術、格子暗号スタディロードマップを公開！！（エンジニア、リサーチャー必読）](https://qiita.com/kenmaro/items/f2d4fb84833c308a4d29)
-  [秘密計算エンジニアを始めて３年が経った。（ついに機械学習モデルの暗号状態での学習について言及します。）](https://qiita.com/kenmaro/items/a1d90a074d552b7bf886)


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

https://grpc.io/docs/languages/cpp/quickstart/

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

として書いています。

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

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

- [CMakeを使ったクライアント・サーバのビルド](https://qiita.com/kenmaro/items/8792b442f4bd47b33c83)
- **[C++でgrpcサーバを実装する](https://qiita.com/kenmaro/items/094803fd8bd50addd055) （　<---- この記事の内容です。）**
- [C++でgrpcクライアントを実装する](https://qiita.com/kenmaro/items/e9326663cd94f67685d0)
- [protobufへのオブジェクトの出し入れについて、tips をまとめる](https://qiita.com/kenmaro/items/da3216d62f9891952a66)


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

https://github.com/kenmaro3/grpc_cpp/tree/step2

今回は、使用ブランチを `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
となります。


## 実行

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

でビルドしたら、

```bash
./myserver
```

でサーバを起動します。

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

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


## まとめ

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

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


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

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



今回はこの辺で。


@kenmaro