grpc - 实例之同步代码:say hello
通过一个grpc实现一个同步的c/s代码,client发送一个空的requset
,server返回一个含有hello
字符串的response
。
1. 定义proto文件
这里使用proto3的语法。
syntax = "proto3"
// response是empty,request中只有一个字段,类型是字符串类型,则如下定义这两个消息
message client_request{
}
message server_reponse{
string words = 1;
}
service SayHello{
rpc hello (client_request) returns (server_reponse) {}
}
2. 生成对应语言的代码
此处生成python对应的代码。
在当前文件夹下创建hello_grpc
目录,存储生成的python代码以及grpc的代码。
python -m grpc_tools.protoc -I=./ --python_out=./hello_grpc --grpc_python_out=./hello_grpc ./hello.proto
3. 实现服务接口
我们刚才在.proto
文件中定义了一个service
服务,且通过protoc编译器生成了对应的python代码;此时通过生成的代码中的服务接口,编写一个类实现SayHelloServicer
接口。
在与hello_grpc
同目录下创建一个hello.py文件,同时需要在hello_grpc
下创建一个__init__.py
文件,且在hello.py
文件同目录下创建一个__init__.py
文件,以用来告诉python解释器hello_grpc
是一个module
。
编写如下类实现该接口。
from hello_grpc.hello_pb2_grpc import SayHelloServicer
from hello_grpc.hello_pb2 import client_request, server_reponse
class Hello(SayHelloServicer):
def hello(self, request, context):
# 声明一个response对象
reponse = server_reponse()
reponse.words = 'hello client! biu~'
return reponse
4. 编写服务端
服务端是为了提供API功能的服务的,所以需要把实现的功能注册到服务器上的某个端口下:
from hello import Hello
from hello_grpc import hello_pb2_grpc
import grpc
from concurrent import futures
if __name__ == "__main__":
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
hello_pb2_grpc.add_SayHelloServicer_to_server(Hello(), server)
server.add_insecure_port('0.0.0.0:8001')
server.start()
server.wait_for_termination()
5. 编写客户端
客户端是为了请求已经被server端实现的服务的,所以需要通过socket连接到服务端对应的端口,请求对应的API方法。
from hello_grpc import hello_pb2_grpc
from hello_grpc import hello_pb2
import grpc
if __name__ == "__main__":
req = hello_pb2.client_request()
channel = grpc.insecure_channel('0.0.0.0:8001')
stub = hello_pb2_grpc.SayHelloStub(channel)
res = stub.hello(req)
print(res)
分别运行python server.py
和python client.py
,服务端会等待一个请求,客户端发送一个请求,服务端返回响应。
程序结果如下: