Как выйти из асинхронного диспетчера из обработчика?

Я не мог найти это в документах, но как я хотел вырваться из asyncore.loop() без использования сигналов?

4 ответа

Решение

Это было быстро разобраться после просмотра исходного кода. Спасибо документам за ссылки непосредственно на источник!

Существует исключение ExitNow, которое вы можете просто вызвать из приложения, которое выходит из цикла.

С использованием EchoHandler Пример из документов, я изменил его, чтобы немедленно выйти при получении данных.

class EchoHandler(asyncore.dispatcher_with_send):

    def handle_read(self):
        data = self.recv(8192)
        if data:
            raise asyncore.ExitNow('Server is quitting!')

Также имейте ввиду, что вы можете поймать ExitNow так что ваше приложение не поднимается, если вы используете его внутри. Это часть моего источника:

def run(config):
    instance = LockServer(config)
    try:
        asyncore.loop()
    except asyncore.ExitNow, e:
        print e

Асинхронный цикл также завершается, когда не осталось никаких соединений, поэтому вы можете просто закрыть соединение. Если у вас несколько соединений, то вы можете использовать asyncore.close_all().

Попробуй это:

Один класс для сервера (расширяет 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)

Другой класс для потока, который собирается управлять сервером (расширяет Thread)... проверьте метод run (), здесь мы вызываем 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()

Теперь для запуска сервера:

# 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..."

Вы заметите, что сервер не сразу умирает... но умирает изящно

Другой подход заключается в использовании параметра count вызова asyncore.loop. Затем вы можете заключить asyncore.loop в другую логику:

while(i_should_continue()):
    asyncore.loop(count=1)

Это не приведет к немедленной остановке открытого соединения или преждевременного истечения времени ожидания. Но это, наверное, хорошая вещь? Я использую это, когда я запускаю сервер прослушивания.

Другие вопросы по тегам