2015-05-13 5 views
1

Я хотел бы остановиться в std lib, если это возможно. Все мои потоки запускаются, и сокеты будут прослушиваться надлежащим образом. Мне нужно уметь грациозно закрывать сокеты, но я не могу вернуться к ним, чтобы нормально завершить работу.Как изящно завершить SocketServer

Проблема в том, что когда я добираюсь до server_close(), он взрывается ко мне (см. Вывод следствия для исключения).

Спасибо, что посмотрели!

import sys 
import threading 
import SocketServer 


class EchoRequestHandler(SocketServer.BaseRequestHandler): 

    def __init__(self, request, client_address, server): 
     SocketServer.BaseRequestHandler.__init__(self, request, client_address, server) 
     return 

    def setup(self): 
     return SocketServer.BaseRequestHandler.setup(self) 

    def handle(self): 
     # Echo the back to the client 
     data = self.request.recv(1024) 
     return 

    def finish(self): 
     return SocketServer.BaseRequestHandler.finish(self) 


class EchoServer(SocketServer.TCPServer): 

    def __init__(self, server_address, handler_class=EchoRequestHandler): 
     SocketServer.TCPServer.__init__(self, server_address, handler_class) 
     return 

    def server_activate(self): 
     SocketServer.TCPServer.server_activate(self) 
     return 

    def serve_forever(self): 
     while True: 
      self.handle_request() 
     return 

    def server_close(self): 
     return SocketServer.TCPServer.server_close(self) 



def bind_sockets(port_list): 

    server_list = [] 
    for port in port_list: 

     server = EchoServer(("", int(port)), EchoRequestHandler) 
     server_thread = threading.Thread(target=server.serve_forever) 
     server_thread.setDaemon(True) 
     server_thread.start() 
     server_list.append(server) 
     print "listening on port", port 

    return server_list 


def main(): 

    port_list = [12345,54321] 

    active_servers = bind_sockets(port_list) 

    print "Hit Q to quit or R to reload." 

    while 1: 
     key_press = sys.stdin.read(1) 

     if key_press == "q": 
      sys.exit(2) 
     elif key_press == "r": 
      #We need to close gracefully so we can go on to do other stuff. 
      print active_servers.__len__() 
      for server in active_servers: 
       server.server_close() 
       print "closed" 


if __name__ == "__main__": 
    main() 

Исключение стека трассировки я получаю:

Exception in thread Thread-1: Traceback (most recent call last): 
File "~snip~/threading.py", line 810, in __bootstrap_inner self.run() 
File "~snip~/threading.py", line 763, in run self.__target(*self.__args, **self.__kwargs) 
File "kill_thread.py", line 36, in serve_forever self.handle_request() 
File "~snip~/SocketServer.py", line 276, in handle_request fd_sets = _eintr_retry(select.select, [self], [], [], timeout) 
File "~snip~/SocketServer.py", line 155, in _eintr_retry return func(*args) error: (9, 'Bad file descriptor') 
+0

Непонятно, что значит «взрывает меня». Что на самом деле происходит? –

+0

Он выдает следующее исключение, затем скрипт зависает до тех пор, пока я не ctrl + c: –

+0

Исключение из потока Thread-1: Traceback (последний последний вызов): Файл «~ snip ~/threading.py», строка 810, в __bootstrap_inner self.run() Файл «~ snip ~/threading.py», строка 763, в запуске self .__ target (* self .__ args, ** self .__ kwargs) Файл «kill_thread.py», строка 36 , в serve_forever self.handle_request() Файл "~ надрез ~/SocketServer.py", строка 276, в handle_request fd_sets = _eintr_retry (select.select, [само], [], [], тайм-аут) файла " ~ snip ~/SocketServer.py ", строка 155, в _eintr_retry return func (* args)Ошибка: (9, «Плохой дескриптор файла») –

ответ

0

У вас есть две проблемы:

  • вам нужно вызвать отключение()
  • Вы не должны отменять server_forever()

like это:

# don't overrule server_forever, the default implementation 
# handles the shutdown() 
#def serve_forever(self): 
# while True: 
#  self.handle_request() 
# return 

def server_close(self): 
    self.shutdown() 
    return SocketServer.TCPServer.server_close(self) 
Смежные вопросы