Я не мог найти это в docs, но как я должен вырваться из asyncore.loop()
без использования сигналов?Как выйти из диспетчера asyncore из обработчика?
ответ
Это было быстро, чтобы разобраться, посмотрев исходный код. Благодаря документам для прямой ссылки на источник!
Существует исключение 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().
Другим подходом является использование параметра count для вызова asyncore.loop. Вы можете обернуть asyncore.loop в другой логике:
while(i_should_continue()):
asyncore.loop(count=1)
Это не будет немедленно прекратить открытое соединение, или преждевременно тайм-аут. Но это, наверное, хорошо? Я использую это, когда запускаю сервер прослушивания.
Попробуйте это:
Один класс для сервера (расширяет 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..."
Вы заметите, что сервер не умирает сразу ... но он умирает изящно
Это, вероятно, правильное решение, если вы хотите, чтобы остановить цикл от «внешней петли». Другие решения, приведенные выше, предназначены для остановки цикла в цикле. –