Fechar escutando socket em thread python

Eu tenho um problema ao tentar aprender sobre sockets para comunicação de rede. Eu fiz um thread simples que ouve conexões e cria processos para conectar clientes, mas meu problema é que eu não consigo fazer o thread se juntar corretamente, pois não encontrei uma maneira de cancelar o socket.accept () – call quando eu quero sair do programa.

Meu código é assim;

class ServerThread( threading.Thread ): def __init__(self, queue, host, port): threading.Thread.__init__(self) self.queue = queue self.running = True self.hostname = host self.port = port def run(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.bind((self.hostname, self.port)) self.socket.listen(1) while self.running: try: conn, address = self.socket.accept() process = Process(target=server_slave, args=(conn, address, self.queue)) process.daemon = True process.start() except socket.timeout: pass def stop(self): self.running = False self.socket.close() 

Eu consegui fechar o programa, definindo self.setDaemon(True) e apenas saindo do programa principal, entregando tudo para o grande coletor de lixo – mas isso parece ser uma solução ruim. Eu também tentei definir um tempo limite para o soquete, mas isso resulta em obter [Errno 35] Resource temporarily unavailable (independentemente do tempo limite real, mesmo quando eu o configurei para anos …).

O que estou fazendo de errado? Eu projetei o segmento de maneira estúpida ou perdi alguma coisa sobre aceitar conexões?

Uma maneira de fechar o encadeamento parece ser fazer uma conexão com o soquete, continuando assim o encadeamento até a conclusão.

 def stop(self): self.running = False socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect( (self.hostname, self.port)) self.socket.close() 

Isso funciona, mas ainda parece que pode não ser o ideal …

Na maioria dos casos, você abrirá um novo thread ou processo assim que a conexão for aceita. Para fechar a conexão, quebre o loop while. A garbage collection removerá o segmento ou processo, mas a associação garantirá que nenhuma seja deixada para trás.

Os sockets persistentes são fechados quando o usuário os fecha ou eles esgotam o tempo limite. Páginas da Web estáticas e não persistentes serão fechadas depois que elas enviarem as informações.

Aqui está um bom exemplo de um servidor de soquete persistente no Python. Ele usa multiprocessing, o que significa que ele pode ser executado em vários núcleos para tarefas ligadas à CPU. Mais comumente conhecido como multithreading.

 import socket import multiprocessing def run(): host = '000.000.000.000' port = 1212 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('', port)) sock.listen(3) while True: p = multiprocessing.Process(target=worker, args=sock.accept()).start() def worker(conn, addr): while True: if data == '': #remote connection closed break if len(dataList) > 2: # do stuff print 'This code is untested' run() 

Uma solução suja que permite sair do programa é usar os._exit(0) .

 def stop(self): self.socket.close() os._exit(0) 

note que sys.exit não funciona / bloqueia. Mas os._exit é o caminho mais baixo e funciona, o que nada mais faz.

Solução parcialmente testada

  1. Coloque self.socket.settimeout(0.1) logo antes, while
  2. Coloque conn.settimeout(None) logo após accept