1 hello.proto
syntax = "proto3"; // 声明使用哪一种的protobuf package test; // 包名称 // 服务 类似视图 service Bibili { // rpc 服务 rpc HelloYoyo (HelloYoyoRequst) returns (HelloYoyoResponse) { } rpc HelloTest (HelloTsetRquest) returns (HelloTestRsponse) { } rpc HelloStream (stream HelloTsetRquest) returns (stream HelloTestRsponse) { // 定义流传输 } rpc TsetClientRectStream (TsetClientRectStreamRequest) returns (stream TsetClientRectStreamRsponse) { } rpc TsetClientSendStream (stream TsetClientSendStreamRequest) returns (TsetClientSendStreamRsponse) { } rpc TsetTowWayStream (stream TsetTowWayStreamRquest) returns (stream TsetTowWayStreamRsponse) { } } message TsetTowWayStreamRquest { string data = 1; } message TsetTowWayStreamRsponse { string result = 1; } message TsetClientSendStreamRequest { string data = 1; } message TsetClientSendStreamRsponse { string result = 1; } message TsetClientRectStreamRequest { string data = 1; } message TsetClientRectStreamRsponse { string result = 1; } message HelloYoyoRequst { string name = 1; int32 age = 2; } message HelloYoyoResponse { string result = 1; } message HelloTsetRquest { string name = 1; int32 age = 2; repeated string data = 3; repeated HelloTsetRsqusetValue lists = 4; // 自己定义数据类型 map<string, int64> number = 5; //注释 map<string, HelloTsetRsqusetValue> value = 6; // 自己定义数据类型 } message HelloTsetRsqusetValue { string name = 1; int32 age = 2; bool is_active = 3; } message HelloTestRsponse { }
2 service.py
import time from concurrent import futures # grcp线程 import grpc import hello_pb2 as pb2 import hello_pb2_grpc as pb2_grcp def _abort(code, detail): def terminate(ingnored_request, context): context.abort(code, detail) return grpc.unary_unary_rpc_method_handler(terminate) # 书写一个拦截器 class TestInterceptor(grpc.ServerInterceptor): def __init__(self, key, value, code, detail): self.key = key self.value = value self._abort = _abort(code, detail) def intercept_service(self, continuation, handler_call_details): ''' :param continuation: 函数执行器 :param handler_call_details: header :return: ''' if (self.key, self.value) not in handler_call_details.invocation_metadata: return self._abort return continuation(handler_call_details) class Bibili(pb2_grcp.BibiliServicer): def HelloYoyo(self, request, context): name = request.name age = request.age if name == "yoyo123": context.set_details("程序出现问题") # 添加一些描述 context.set_code(grpc.StatusCode.DATA_LOSS) # 设置code码 raise context # 抛出异常 context.set_trailing_metadata((("name", "yoyo"), ("key", "vlaue"))) # 给客户端传输消息 headers = context.invocation_metadata() # 接受客户端传输过来的消息 print(headers) print(headers[0].key, headers[0].value) result = "my name is {}, i am {} year old".format(name, age) context.set_compression(grpc.Compression.Gzip) # 数据压缩 只针对这个函数内的内容 return pb2.HelloYoyoResponse(result=result) def TsetClientRectStream(self, request, context): index = 0 while context.is_active(): data = request.data if data == 'close': print('data is close, request will cancel') context.cancel() # 关闭 time.sleep(1) index += 1 yield pb2.TsetClientRectStreamRsponse(result="send{}: {}".format(index, data)) def TsetClientSendStream(self, request_iterator, context): index = 0 for request in request_iterator: print(request.data) if index == 10: break index += 1 return pb2.TsetClientSendStreamRsponse(result="ok") def TsetTowWayStream(self, request_iterator, context): index = 0 for request in request_iterator: data = request.data print(data) if index == 10: context.cancel() # 关闭 index += 1 yield pb2.TsetTowWayStreamRsponse(result="service send {}".format(data)) def run(): validator = TestInterceptor("name", "yoyo", grpc.StatusCode.UNAUTHENTICATED, "Access denined") grpc_server = grpc.server( futures.ThreadPoolExecutor(max_workers=4), # 设置工作时最大的线程数量 compression=grpc.Compression.Gzip, # 设置压缩, 针对这个服务器所有的内容 interceptors=(validator,), options=[("grpc.max_send_message_length", 50 * 1024 * 1024), # grpc.max_send_message_length:设置发送数据的最大数量 ("grpc.max_receive_message_length", 50 * 1024 * 2014)] # grpc.max_receive_message_length:设置接收数据的最大数量 ) pb2_grcp.add_BibiliServicer_to_server(Bibili(), grpc_server) # 注册Bibili到grpc_server中 grpc_server.add_insecure_port("0.0.0.0:5000") # 绑定ip和端口 print("server will start at 0.0.0.0:5000") grpc_server.start() # 启动 try: while 1: time.sleep(3600) # 堵塞在这里 except KeyboardInterrupt: grpc_server.stop(0) # 结束 if __name__ == "__main__": run()
3 client.py
import random import time import grpc import hello_pb2 as pb2 import hello_pb2_grpc as pb2_grpc def test(): index = 0 while True: time.sleep(1) data = str(random.random()) if index == 5: break index += 1 yield pb2.TsetClientSendStreamRequest(data=data) def run(): conn = grpc.insecure_channel("0.0.0.0:5000") # 定义一个频道 client = pb2_grpc.BibiliStub(channel=conn) # 生成客户端 try: response, call = client.HelloYoyo.with_call(pb2.HelloYoyoRequst(name="yoyo", age=33), compression=grpc.Compression.Gzip, wait_for_ready=True, metadata=(("clicent_key", "client_value"),)) # metadata 给服务器传输消息 grpc.Compression.Gzip:压缩数据 print(response.result) headers = call.trailing_metadata() # 接受服务器传输过来的消息 print(headers) print(headers[0].key, headers[0].value) # print(help(client.HelloYoyo.with_call)) except Exception as e: print(dir(e)) # 查看对像内所有属于及方法 print(e.code(), e.code().name, e.code().value) print(e.details()) # response = client.TsetClientRectStream(pb2.TsetClientRectStreamRequest(data='yoyo')) # for item in response: # print(item.result) # response = client.TsetClientSendStream(test()) # print(response.result) # response = client.TsetTowWayStream(test(), timeout=10) # 请求超时时长 # for request in response: # print(request.result) if __name__ == "__main__": run()