@kenmaroです。
普段は主に秘密計算、準同型暗号などの記事について投稿しています。
秘密計算に関連するまとめの記事に関しては以下をご覧ください。
概要
grpcをC++を用いて実装するときの、公式チュートリアル
を終えた後に行うと理解が深まるチュートリアル
として書いています。
今回のチュートリアルの構成
以下の流れで記事を分けて書いており、この記事は第二回の内容となります。
- CMakeを使ったクライアント・サーバのビルド
- C++でgrpcサーバを実装する ( <---- この記事の内容です。)
- C++でgrpcクライアントを実装する
- protobufへのオブジェクトの出し入れについて、tips をまとめる
準備
前回も使用したチュートリアルレポジトリを使います。
今回は、使用ブランチを step2
として下さい。クローンした後にブランチを移動する場合、
git checkout -b step2 origin/step2
として下さい。
前回とのレポジトリの変更点は
controller/myserver.cpp
のみとなります。
サーバサイドの実装
controller/myserver.cpp
をみて下さい。
後半部分の void RunServer(){}
関数以下は基本的にはテンプレとなります。
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
にて実際の関数の中身を書いていくことになります。
今回は、各関数はプリントを行うだけで何もしない関数として定義しています。
第四回にて、実際にクライアントサイドからデータを受け取り、実際の操作を行った上でクライアント側に結果を渡すようなコードを実装しようと思います。
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についての知識を全て書いていくべく、
数回にわけてチュートリアル(公式のチュートリアルの次に行いたいこと)をまとめて行っています。
今回は第二回として、サーバサイドを簡易的に実装しました。
誰かの役に立てれば幸いです。
次回も是非ご覧ください。
今回はこの辺で。