Ich glaube, die Absicht des OP ist der Server aus dem Request-Handler schließen und ich denke, , dass der KeyboardInterrupt
Aspekt seines Codes nur Dinge verwirrend ist.
Drücken von ctrl-c
aus der Shell, in der der Server läuft wird erfolgreich in herunterfahren, ohne etwas Besonderes zu tun. Sie können nicht ctrl-c
aus einer anderen Schale drücken und erwarten, dass es zu arbeiten, und ich denke, dass Begriff kann sein, wo dies verwirrend Code herkommt. Es gibt keine Notwendigkeit, die KeyboardInterrupt
in handle()
zu handhaben als die OP versucht, oder um serve_forever()
als andere vorgeschlagen. Wenn Sie dies nicht tun, funktioniert es wie erwartet.
Der einzige Trick hier - und es ist schwierig - ist der Server zum Herunterfahren aus dem Handler zu sagen ohne Deadlocks.
Als OP erklärt und in seinem Code gezeigt, er ist ein Single-Threaded-Server, so dass der Benutzer, der es in der „anderen Thread“ shut vorgeschlagen, nach unten ist nicht aufpasst.
grub ich um den SocketServer
Code und entdecken, dass die BaseServer
Klasse, in seinem Bemühen, mit dem Gewinden Mixins in diesem Modul zu arbeiten, macht es tatsächlich schwieriger mit gewindelosen Servern zu verwenden, indem ein threading.Event
um die Verwendung von Schleife in serve_forever
.
Also schrieb ich eine modifizierte Version von serve_forever
für single-threaded-Server, die es ermöglicht, den Server vom Request-Handler herunterzufahren.
import SocketServer
import socket
import select
class TCPServerV4(SocketServer.TCPServer):
address_family = socket.AF_INET
allow_reuse_address = True
def __init__(self, server_address, RequestHandlerClass):
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
self._shutdown_request = False
def serve_forever(self, poll_interval=0.5):
"""provide an override that can be shutdown from a request handler.
The threading code in the BaseSocketServer class prevented this from working
even for a non-threaded blocking server.
"""
try:
while not self._shutdown_request:
# XXX: Consider using another file descriptor or
# connecting to the socket to wake this up instead of
# polling. Polling reduces our responsiveness to a
# shutdown request and wastes cpu at all other times.
r, w, e = SocketServer._eintr_retry(select.select, [self], [], [],
poll_interval)
if self in r:
self._handle_request_noblock()
finally:
self._shutdown_request = False
class TCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
data = self.request.recv(4096)
if data == "shutdown":
self.server._shutdown_request = True
host = 'localhost'
port = 52000
server = TCPServerV4((host, port), TCPHandler)
server.serve_forever()
Wenn Sie die Zeichenfolge 'shutdown'
an den Server senden, wird der Server seine serve_forever
Schleife beenden. Sie können netcat zu testen, verwenden:
printf "shutdown" | nc localhost 52000
separaten Thread: http://StackOverflow.com/Questions/268629/How-to-Stop-Basehttpserver-serve-Foree-in-A-Basehttprequesthandler-Unterklasse –