Skip to content

Commit 731650d

Browse files
committed
update server
1 parent dcde81e commit 731650d

1 file changed

Lines changed: 147 additions & 3 deletions

File tree

‎server.py‎

Lines changed: 147 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from typing import Union
22
from thrift import Thrift
33
from thrift.protocol import TBinaryProtocol
4-
from thrift.server import TServer
4+
from thrift.protocol.THeaderProtocol import THeaderProtocolFactory
5+
from thrift.server.TServer import TServer
56
from thrift.transport import TSocket, TTransport
67
from soccer import Game
78
from soccer.ttypes import State, Empty, PlayerActions, CoachActions, TrainerActions
@@ -12,6 +13,149 @@
1213
from threading import Semaphore
1314
import os
1415
import sys
16+
import threading
17+
import queue
18+
import logging as logger
19+
20+
import asyncio
21+
22+
def start_loop(loop):
23+
asyncio.set_event_loop(loop)
24+
loop.run_forever()
25+
26+
def run_async_func_in_new_thread(target, *args):
27+
new_loop = asyncio.new_event_loop()
28+
t = threading.Thread(target=start_loop, args=(new_loop,))
29+
t.start()
30+
31+
asyncio.run_coroutine_threadsafe(target(*args), new_loop)
32+
class TThreadedServer2(TServer):
33+
"""Threaded server that spawns a new thread per each connection."""
34+
35+
def __init__(self, *args, **kwargs):
36+
TServer.__init__(self, *args)
37+
self.daemon = kwargs.get("daemon", False)
38+
39+
def serve(self):
40+
self.serverTransport.listen()
41+
while True:
42+
try:
43+
client = self.serverTransport.accept()
44+
if not client:
45+
continue
46+
t = threading.Thread(target=self.start_event_loop, args=(client,))
47+
# run_async_func_in_new_thread(self.handle, client)
48+
49+
# t = threading.Thread(target=self.handle, args=(client,))
50+
t.setDaemon(self.daemon)
51+
t.start()
52+
except KeyboardInterrupt:
53+
raise
54+
except Exception as x:
55+
logger.exception(x)
56+
57+
def start_event_loop(self, client):
58+
loop = asyncio.new_event_loop()
59+
asyncio.set_event_loop(loop)
60+
loop.run_until_complete(self.handle(client))
61+
loop.close()
62+
63+
async def handle(self, client):
64+
itrans = self.inputTransportFactory.getTransport(client)
65+
iprot = self.inputProtocolFactory.getProtocol(itrans)
66+
67+
# for THeaderProtocol, we must use the same protocol instance for input
68+
# and output so that the response is in the same dialect that the
69+
# server detected the request was in.
70+
if isinstance(self.inputProtocolFactory, THeaderProtocolFactory):
71+
otrans = None
72+
oprot = iprot
73+
else:
74+
otrans = self.outputTransportFactory.getTransport(client)
75+
oprot = self.outputProtocolFactory.getProtocol(otrans)
76+
77+
try:
78+
while True:
79+
await self.processor.process(iprot, oprot)
80+
except TTransport.TTransportException:
81+
pass
82+
except Exception as x:
83+
logger.exception(x)
84+
85+
itrans.close()
86+
if otrans:
87+
otrans.close()
88+
89+
class TThreadPoolServer2(TServer):
90+
"""Server with a fixed size pool of threads which service requests."""
91+
92+
def __init__(self, *args, **kwargs):
93+
TServer.__init__(self, *args)
94+
self.clients = queue.Queue()
95+
self.threads = 10
96+
self.daemon = kwargs.get("daemon", False)
97+
98+
def setNumThreads(self, num):
99+
"""Set the number of worker threads that should be created"""
100+
self.threads = num
101+
102+
def serveThread(self):
103+
"""Loop around getting clients from the shared queue and process them."""
104+
while True:
105+
try:
106+
client = self.clients.get()
107+
self.serveClient(client)
108+
except Exception as x:
109+
logger.exception(x)
110+
111+
def serveClient(self, client):
112+
"""Process input/output from a client for as long as possible"""
113+
itrans = self.inputTransportFactory.getTransport(client)
114+
iprot = self.inputProtocolFactory.getProtocol(itrans)
115+
116+
# for THeaderProtocol, we must use the same protocol instance for input
117+
# and output so that the response is in the same dialect that the
118+
# server detected the request was in.
119+
if isinstance(self.inputProtocolFactory, THeaderProtocolFactory):
120+
otrans = None
121+
oprot = iprot
122+
else:
123+
otrans = self.outputTransportFactory.getTransport(client)
124+
oprot = self.outputProtocolFactory.getProtocol(otrans)
125+
126+
try:
127+
while True:
128+
self.processor.process(iprot, oprot)
129+
except TTransport.TTransportException:
130+
pass
131+
except Exception as x:
132+
logger.exception(x)
133+
134+
itrans.close()
135+
if otrans:
136+
otrans.close()
137+
138+
def serve(self):
139+
"""Start a fixed number of worker threads and put client into a queue"""
140+
for i in range(self.threads):
141+
try:
142+
t = threading.Thread(target=self.serveThread)
143+
t.setDaemon(self.daemon)
144+
t.start()
145+
except Exception as x:
146+
logger.exception(x)
147+
148+
# Pump the socket for clients
149+
self.serverTransport.listen()
150+
while True:
151+
try:
152+
client = self.serverTransport.accept()
153+
if not client:
154+
continue
155+
self.clients.put(client)
156+
except Exception as x:
157+
logger.exception(x)
158+
15159

16160
class GameHandler:
17161
def __init__(self):
@@ -89,8 +233,8 @@ def serve(port):
89233
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
90234

91235
# server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
92-
server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
93-
server.setNumThreads(50)
236+
server = TThreadedServer2(processor, transport, tfactory, pfactory)
237+
# server.setNumThreads(50)
94238
print("Thrift server started at port 50051")
95239
try:
96240
handler.running.acquire()

0 commit comments

Comments
 (0)