2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C++ を用いて grpc を実装したい人生だった。【クライアントサイドの実装】

Last updated at Posted at 2022-02-15

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

概要

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

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

として書いています。

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

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

準備

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

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

git checkout -b step3 origin/step3

として下さい。

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

client.cpp

のみとなります。

クライアントサイドの実装

client.cpp
# include "controller/common.h"

using namespace std;
using namespace grpc;

int main(){
  printf("hello, world!\n");
  //auto channel = CreateChannel("localhost:5001", InsecureChannelCredentials());
  //auto stub = MyServer::NewStub(channel);
  std::shared_ptr<grpc::Channel> channel = CreateChannel("localhost:5001", InsecureChannelCredentials());
  std::unique_ptr< MyServer::Stub> stub = MyServer::NewStub(channel);

  //================================================
  printf("[Client] test1 called.\n");
  ClientContext context_for_test1;
  PB_Message pb_send_for_test1;
  PB_Message reply_for_test1;

  stub->test1(&context_for_test1, pb_send_for_test1, &reply_for_test1);
  printf("[Client] test1 done.\n");

  //================================================
  printf("[Client] test2 called.\n");
  ClientContext context_for_test2;
  PB_DoubleList pb_send_for_test2;
  PB_DoubleList reply_for_test2;

  stub->test2(&context_for_test2, pb_send_for_test2, &reply_for_test2);
  printf("[Client] test2 done.\n");

  //================================================
  printf("[Client] test3 called.\n");
  ClientContext context_for_test3;
  PB_Data pb_send_for_test3;
  PB_Data reply_for_test3;

  stub->test3(&context_for_test3, pb_send_for_test3, &reply_for_test3);
  printf("[Client] test3 done.\n");
}

追加された上のコードでは、
サーバサイドの3つの関数

myserver.proto
service MyServer{
  rpc test1(PB_Message) returns (PB_Message){};
  rpc test2(PB_DoubleList) returns (PB_DoubleList){};
  rpc test3(PB_Data) returns (PB_Data){};
}

をそれぞれ呼んでいます。

注意点として、

  • ClientContextのポインタ
  • 関数の入力となるものの実体
  • 関数の出力となるもののポインタ

を渡す必要があるということです。

また、stubは auto でイニシャライズすることができますが、
明示的に型を一応書いています。
このように、stubはunique_pointer の形でイニシャライズされるため、
stubが関数を超えてメモリに残り、メモリリークなどを起こしてしまうことは考えなくてよいような設計となっているようです。

実行

いつものように

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

でビルドしたら、ターミナルを二つ開いて下さい。
両方ともbuild フォルダに移動し、

./myserver

でサーバを起動します。そして、

./client

でクライアントのコードを走らせて下さい。

サーバ側の関数が実際に呼ばれ、サーバサイドを走らせているターミナル上に

root@8233ca8d11d9:/grpc_cpp/build# ./myserver
hello, world
Server listening on 0.0.0.0:5001
[ServerService: test1] called.
[ServerService: test1] done.
[ServerService: test2] called.
[ServerService: test2] done.
[ServerService: test3] called.
[ServerService: test3] done.

と表示されれば大丈夫です。ちなみに、
クライアントサイドには

root@8233ca8d11d9:/grpc_cpp/build# ./client
hello, world!
[Client] test1 called.
[Client] test1 done.
[Client] test2 called.
[Client] test2 done.
[Client] test3 called.
[Client] test3 done.

と表示されるはずです。

次回は具体的にprotobufにデータを出し入れします

今回は、簡易的にprotobufをディフォルトコンストラクタでイニシャライズし、
そのままクライアントからサーバに送りました。

しかし、もちろん実際のサービスでは
クライアントが意味のあるデータをサーバに送り、サーバ側ではデータを受け取り、
何か処理を行なってからクライアント側に返すはずです。

そのときに必要になるのが、protobufへの実際のデータの出し入れです。

すなわち、

  • クライアント側でデータをprotobufに格納 (1)
  • 送る
  • サーバはprotobufを受け取って、クラスオブジェクトに変換する (2)
  • 処理する
  • クライアントに送るためにprotobufに格納 (3)
  • 返却する

という流れとなります。このうちの (1), (2), (3) を実際にコーディングしてみます。

まとめ

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

今回は第三回として、クライアントサイドを簡易的に実装しました。

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

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

今回はこの辺で。

@kenmaro

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?