【gRPC】c++のserverとpythonのclientでHello Worldする

前回、gRPCのc++の環境をbuildしたのでそれを利用して、今回はc++のserverとpythonのclientでHello Worldしたいと思います。

gRPCのc++の環境をbuildについては、前回の記事↓を参考にしてください。

https://tyojugiga.hatenablog.com/entry/2019/09/13/004215

また、この記事に出てくるソースコードは以下↓を参考にしています。

https://github.com/grpc/grpc/tree/v1.23.0/examples

 

環境

OS:Windows10 home
Visual Studio:2019
Python:3.7
 

protoファイルを作成する

protoファイル(helloworld.proto)は以下の通りになります。

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

c++のserverをつくる

まずc++への翻訳のため先ほど作成したprotoファイルをもとにprotocol bufferを実行します。
前回の記事でbuildしたprotoc.exeとgrpc_cpp_plugin.exeのあるディレクトリにprotoファイルを移動します。
そうしたらコマンドプロンプトを起動してそのディレクトリに移動したうえで以下を実行します。

$protoc.exe -I=. --grpc_out=. --plugin=protoc-gen-grpc=.\grpc_cpp_plugin.exe helloworld.proto

$protoc.exe -I=. --cpp_out=. helloworld.proto

すると以下のファイルが生成されます。

helloworld.pb.h
helloworld.pb.cc
helloworld.grpc.pb.h
helloworld.grpc.pb.cc

次にserverのc++のソースファイルを作成します。
visual studioを開いてc++のプロジェクトを作成します。
server.cppは以下のようになります。

#include <iostream>
#include <memory>
#include <string>

#include <grpc++/grpc++.h>

#include "helloworld.grpc.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;

class GreeterServiceImpl final : public Greeter::Service {
	Status SayHello(ServerContext* context, const HelloRequest* request,
		HelloReply* reply) override {
		std::string prefix("Hello ");
		reply->set_message(prefix + request->name());
		return Status::OK;
	}
};

void RunServer() {
	std::string server_address("0.0.0.0:50051");
	GreeterServiceImpl service;

	ServerBuilder builder;
	
	builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
	
	builder.RegisterService(&service);
	
	std::unique_ptr<Server> server(builder.BuildAndStart());
	std::cout << "Server listening on " << server_address << std::endl;

	server->Wait();
}

int main(int argc, char** argv) {
	RunServer();

	return 0;
}

先ほど生成された以下のファイルをソースファイルとヘッダーファイルに追加します。
helloworld.pb.h
helloworld.pb.cc
helloworld.grpc.pb.h
helloworld.grpc.pb.cc

次にincludeパスに以下のディレクトリを追加します。

自分のパス\grpc\include
自分のパス\grpc\third_party\protobuf\src\

f:id:tyojugiga:20190916213327p:plain

次に前回の記事でbuildした以下のファイル名を追加の依存ファイルに追加します。
libprotobuf.lib
grpc.lib
gpr.lib
grpc_unsecure.lib
grpc++_unsecure.lib
Ws2_32.lib
libeay32.lib
ssleay32.lib
zlib.lib

f:id:tyojugiga:20190916213849p:plain

上記libファイルのパスも追加します。(Ws2_32.lib以外)

f:id:tyojugiga:20190916214305p:plain


次に以下を追加します。

  • D_WIN32_WINNT=0x0600

f:id:tyojugiga:20190916214544p:plain

最後にランタイムライブラリをMTにします。

f:id:tyojugiga:20190916214913p:plain

これでbuildできるはずです!!

pythonのclientをつくる

まずライブラリをインストールします。

$ pip install grpcio-tools

次に以下のコードを作成し、先ほど作成したprotoファイルの場所で実行します。

from grpc_tools import protoc

protoc.main(
    (
        '',
        '-I.',
        '--python_out=.',
        '--grpc_python_out=.',
        './helloworld.proto',
    )
)


するとc++の時と同じように以下のファイルが生成されます。
helloworld_pb2.py
helloworld_pb2_grpc.py

次にclientのコード(client.py)を作成します。

from __future__ import print_function
import logging

import grpc

import helloworld_pb2
import helloworld_pb2_grpc


def run():
    with grpc.insecure_channel('localhost:50051') as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        response = stub.SayHello(helloworld_pb2.HelloRequest(name='world'))
    print("Greeter client received: " + response.message)


logging.basicConfig()
run()

client側はこれで完成です。

Hello Worldの実行

それではコマンドプロンプトを二つ起動させてserver→clientの順で実行します。
すると以下のようになるはずです。
f:id:tyojugiga:20190916220529p:plain

Hello Worldできました!!

ここまで読んでいただきありがとうございます!
ご意見、ご質問等ありましたらコメントしていただけると嬉しいです。