How to quit an asyncore dispatcher from a handler?

拟墨画扇 提交于 2020-01-20 05:04:24

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!