我有一个基于Python 3的套接字服务器,监听TCP连接。 它工作得很好,但现在我希望能够关闭整个应用程序"优雅",即使还有一个或多个客户端仍然连接到服务器。
以下代码只是演示了结构,我删除了一些对问题不重要的函数:
def createContentHandler(server = None):
"""
Creates TCP Request Handler with given message handler
"""
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
"""
Request handler in a loop receives and handles message and send back response
"""
id = threading.get_ident()
sock = self.request
try:
while True:
msg = self.receiveMessage()
data = msg.decode("utf-8")
response = server._msghandler.handle(data)
self.sendMessage(response)
except ConnectionResetError as e:
sock.close()
print("socket close by client")
except Exception as e:
sock.close()
print("socket close by other reason")
return ThreadedTCPRequestHandler
#======================== CLASS =====================================
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
"""
Handle each request in a separate thread.
"""
#======================== CLASS =====================================
class Socket_Server():
def __init__(self, *, adress, port, msghandler):
super(Socket_Server, self).__init__()
self._adress = adress
self._port = port
self._msghandler = msghandler
def run(self):
print('TCP socket server starting...')
server_address = (self._adress, self._port)
tcpHandler = createContentHandler(self)
print('TCP socket server is running.')
with ThreadedTCPServer(server_address, tcpHandler) as server:
self._server = server
server.serve_forever(0.5)
def shutdown(self):
if self._server is not None:
self._server.shutdown()
self._server.server_close()
print("Server is shut down")
原则上,服务器由server.serve_forever()
启动,并且(由于背后的一些魔力),内容处理程序在每个连接的单独线程中启动。
内容处理程序调用{{1}},内部调用self.receiveMessage()
以从套接字接收数据。这个电话是封锁的。
当我想关闭应用程序时,我从主线程调用服务器上的sock.recv(count)
。我收到消息shutdown()
,但应用程序仍然挂在执行阻止接收的位置。仅当所有客户端都已断开连接时,由于处理"Server is shut down"
。
如何强制连接的内容处理程序按需关闭?实际上我必须打破内容处理程序中循环内的阻塞调用,但是如何?