2017-02-17 19 views
1

У меня есть некоторый код выполняется в потоке, чтобы ждать входящего соединения с клиентом с помощью сокета:нагрузочного контура селектора с использованием потока в Python 3

import threading 
import socket 
import selectors 

class Server(threading.Thread): 
    def __init__(self): 
     # instantiate socket 
     self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

     # bind the socket 
     self.socket.bind(("localhost", 50000)) 

    def run(self): 
     # create selector to interface with OS 
     sel = selectors.DefaultSelector() 

     # register the connection handler for when a client connects 
     sel.register(self.socket, selectors.EVENT_READ, self.handle_connection) 

     while True: 
      events = sel.select() 
      for key, _ in events: 
       # run the callback 
       key.data() 

    def handle_connection(self): 
     # handle a request on the socket 
     data = self._socket.accept() 

     # do stuff with data... 

    def stop(self): 
     # what to do? 
     pass 

Этот код входит в цикл while True и вызывает sel.select() какие блоки пока что-то не прочитано с self._socket, после чего он вызывает обратный вызов self.handle_connection (не относящийся к моему вопросу). Это хорошо работает, но то, что я также хотел бы сделать, это разбить цикл while True с использованием метода потока stop, так что мой основной программный цикл в другом месте может остановить поток и изящно закрыть сервер.

Я не могу просто отметить флаг, как while self.running:, потому что sel.select() блокирует, пока что-то не прочитано. Я также думал об использовании механизма обработки ошибок селектора, но я не обязательно хочу отключать сервер только во время ошибок/исключений.

Кажется, мне нужен селектор для чтения из второго потока, который будет содержать специальную команду, чтобы остановить цикл, но это кажется слишком сложным. Мы ценим любые предложения!

+0

Может быть, параметр 'timeout' в' select' поможет? https://docs.python.org/3.4/library/selectors.html#selectors.BaseSelector.select – Highstaker

+0

Ах да, вот и все! Я добавил 1-й тайм-аут и изменил цикл 'while True' на' while self.server_running' и сделал метод 'stop' set' self.server_running = False'. Так просто! Спасибо. – Sean

+0

Нет проблем! Я отправлю ответ, чтобы другие люди могли его использовать, как предлагается здесь https://meta.stackexchange.com/questions/291167/posting-an-answer-after-posting-it-in-comment-that-solved- что-OPS-проблема/291168 # 291168 – Highstaker

ответ

2

Поскольку вы сказали, что ты в порядке с использованием while self.flag вместо while True, вы можете задать параметр timeout, as explained in the docs. Просто не забудьте проверить свои данные перед вводом петли for key, _ in events: