xref: /aosp_15_r20/external/grpc-grpc/examples/python/data_transmission/server.py (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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