问题
I couldn't find this in the docs, but how am I meant to break out of the asyncore.loop()
without using signals?
回答1:
That was quick to work out after looking at the source code. Thanks to the docs for linking directly to the source!
There is an ExitNow exception you can simply raise from the app, which exits the loop.
Using the EchoHandler
example from the docs, I've modified it to quit immediately when receiving data.
class EchoHandler(asyncore.dispatcher_with_send):
def handle_read(self):
data = self.recv(8192)
if data:
raise asyncore.ExitNow('Server is quitting!')
Also, keep in mind that you can catch ExitNow
so your app doesn't raise if you're using it internally. This is some of my source:
def run(config):
instance = LockServer(config)
try:
asyncore.loop()
except asyncore.ExitNow, e:
print e
回答2:
The asyncore loop also quits when there are no connections left, so you could just close the connection. If you have multiple connections going on then you can use asyncore.close_all().
回答3:
Try this:
One class for the server (extends asyncore.dispatcher):
class Server(asyncore.dispatcher):
def __init__(self, port):
asyncore.dispatcher.__init__(self)
self.host = socket.gethostname()
self.port = port
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((self.host, self.port))
self.listen(5)
print "[Server] Listening on {h}:{p}".format(h=self.host, p=self.port)
def handle_accept(self):
pair = self.accept()
if pair is not None:
sock, addr = pair
print "[ServerSocket] We got a connection from {a}".format(a=addr)
SocketHandler(sock)
Another class for the thread who is going to manage the server (extends Thread)...check the run() method, there is where we call asyncore.loop():
class ServerThread(threading.Thread):
def __init__(self, port):
threading.Thread.__init__(self)
self.server = Server(port)
def run(self):
asyncore.loop()
def stop(self):
self.server.close()
self.join()
Now to start the server:
# This is the communication server, it is going to listen for incoming connections, it has its own thread:
s = ServerThread(PORT)
s.start() # Here we start the thread for the server
print "Server is ready..."
print "Is ServerThread alive? {t}".format(t=str(s.is_alive()))
raw_input("Press any key to stop de server now...")
print "Trying to stop ServerThread..."
s.stop()
print "The server will die in 30 seconds..."
You will note that the server doesn't die immediately... but it dies gracefully
回答4:
Another approach is to use the count parameter of asyncore.loop call. You can then wrap asyncore.loop in other logic:
while(i_should_continue()):
asyncore.loop(count=1)
This won't immediately stop an open connection, or prematurely timeout. But this is probably a good thing? I'm using this when I start a listening server.
来源:https://stackoverflow.com/questions/10490077/how-to-quit-an-asyncore-dispatcher-from-a-handler