1# Copyright 2019 gRPC authors. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""The example of four ways of data transmission using gRPC in Python.""" 15 16from concurrent import futures 17from threading import Thread 18 19import grpc 20 21import demo_pb2 22import demo_pb2_grpc 23 24__all__ = "DemoServer" 25SERVER_ADDRESS = "localhost:23333" 26SERVER_ID = 1 27 28 29class DemoServer(demo_pb2_grpc.GRPCDemoServicer): 30 # 一元模式(在一次调用中, 客户端只能向服务器传输一次请求数据, 服务器也只能返回一次响应) 31 # unary-unary(In a single call, the client can only send request once, and the server can 32 # only respond once.) 33 def SimpleMethod(self, request, context): 34 print( 35 "SimpleMethod called by client(%d) the message: %s" 36 % (request.client_id, request.request_data) 37 ) 38 response = demo_pb2.Response( 39 server_id=SERVER_ID, 40 response_data="Python server SimpleMethod Ok!!!!", 41 ) 42 return response 43 44 # 客户端流模式(在一次调用中, 客户端可以多次向服务器传输数据, 但是服务器只能返回一次响应) 45 # stream-unary (In a single call, the client can transfer data to the server several times, 46 # but the server can only return a response once.) 47 def ClientStreamingMethod(self, request_iterator, context): 48 print("ClientStreamingMethod called by client...") 49 for request in request_iterator: 50 print( 51 "recv from client(%d), message= %s" 52 % (request.client_id, request.request_data) 53 ) 54 response = demo_pb2.Response( 55 server_id=SERVER_ID, 56 response_data="Python server ClientStreamingMethod ok", 57 ) 58 return response 59 60 # 服务端流模式(在一次调用中, 客户端只能一次向服务器传输数据, 但是服务器可以多次返回响应) 61 # unary-stream (In a single call, the client can only transmit data to the server at one time, 62 # but the server can return the response many times.) 63 def ServerStreamingMethod(self, request, context): 64 print( 65 "ServerStreamingMethod called by client(%d), message= %s" 66 % (request.client_id, request.request_data) 67 ) 68 69 # 创建一个生成器 70 # create a generator 71 def response_messages(): 72 for i in range(5): 73 response = demo_pb2.Response( 74 server_id=SERVER_ID, 75 response_data="send by Python server, message=%d" % i, 76 ) 77 yield response 78 79 return response_messages() 80 81 # 双向流模式 (在一次调用中, 客户端和服务器都可以向对方多次收发数据) 82 # stream-stream (In a single call, both client and server can send and receive data 83 # to each other multiple times.) 84 def BidirectionalStreamingMethod(self, request_iterator, context): 85 print("BidirectionalStreamingMethod called by client...") 86 87 # 开启一个子线程去接收数据 88 # Open a sub thread to receive data 89 def parse_request(): 90 for request in request_iterator: 91 print( 92 "recv from client(%d), message= %s" 93 % (request.client_id, request.request_data) 94 ) 95 96 t = Thread(target=parse_request) 97 t.start() 98 99 for i in range(5): 100 yield demo_pb2.Response( 101 server_id=SERVER_ID, 102 response_data="send by Python server, message= %d" % i, 103 ) 104 105 t.join() 106 107 108def main(): 109 server = grpc.server(futures.ThreadPoolExecutor()) 110 111 demo_pb2_grpc.add_GRPCDemoServicer_to_server(DemoServer(), server) 112 113 server.add_insecure_port(SERVER_ADDRESS) 114 print("------------------start Python GRPC server") 115 server.start() 116 server.wait_for_termination() 117 118 # If raise Error: 119 # AttributeError: '_Server' object has no attribute 'wait_for_termination' 120 # You can use the following code instead: 121 # import time 122 # while 1: 123 # time.sleep(10) 124 125 126if __name__ == "__main__": 127 main() 128