python multithreading sockets recv

¿Cómo aborto un socket.recv() desde otro hilo en Python?



multithreading sockets (5)

Encontré una solución usando tiempos de espera. Eso interrumpirá el recv (en realidad antes de que expire el tiempo de espera, lo cual es bueno):

# Echo server program import socket from threading import Thread import time class ClientThread(Thread): def __init__(self, clientSocke): Thread.__init__(self) self.clientSocket = clientSocket def run(self): while 1: try: data = self.clientSocket.recv(1024) print "Got data: ", data self.clientSocket.send(data) except socket.timeout: # If it was a timeout, we want to continue with recv continue except: break self.clientSocket.close() HOST = '''' PORT = 6000 serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) serverSocket.bind((HOST, PORT)) serverSocket.listen(1) clientSocket, addr = serverSocket.accept() clientSocket.settimeout(1) print ''Got a new connection from: '', addr clientThread = ClientThread(clientSocket) clientThread.start() # Close it down immediatly clientSocket.close()

Tengo un hilo principal que espera la conexión. Genera hilos de clientes que harán eco de la respuesta del cliente (telnet en este caso). Pero diga que quiero cerrar todos los sockets y todos los hilos después de un tiempo, como después de 1 conexión. ¿Cómo lo haría? Si hago clientSocket.close () desde el hilo principal, no dejará de hacer el recv. Solo se detendrá si primero envío algo a través de telnet, luego fallará haciendo más envíos y recvs.

Mi código se ve así:

# Echo server program import socket from threading import Thread import time class ClientThread(Thread): def __init__(self, clientSocket): Thread.__init__(self) self.clientSocket = clientSocket def run(self): while 1: try: # It will hang here, even if I do close on the socket data = self.clientSocket.recv(1024) print "Got data: ", data self.clientSocket.send(data) except: break self.clientSocket.close() HOST = '''' PORT = 6000 serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) serverSocket.bind((HOST, PORT)) serverSocket.listen(1) clientSocket, addr = serverSocket.accept() print ''Got a new connection from: '', addr clientThread = ClientThread(clientSocket) clientThread.start() time.sleep(1) # This won''t make the recv in the clientThread to stop immediately, # nor will it generate an exception clientSocket.close()


No estoy seguro pero quizás puedas buscar pares de conectores


No sé si es posible hacer lo que me pides, pero no debería ser necesario. Simplemente no lea desde el socket si no hay nada que leer; use select.select para verificar el socket de datos.

cambio:

data = self.clientSocket.recv(1024) print "Got data: ", data self.clientSocket.send(data)

a algo más como esto:

r, _, _ = select.select([self.clientSocket], [], []) if r: data = self.clientSocket.recv(1024) print "Got data: ", data self.clientSocket.send(data)

EDITAR: Si desea evitar la posibilidad de que el socket se haya cerrado, socket.error .

do_read = False try: r, _, _ = select.select([self.clientSocket], [], []) do_read = bool(r) except socket.error: pass if do_read: data = self.clientSocket.recv(1024) print "Got data: ", data self.clientSocket.send(data)


Sé que este es un hilo viejo y que probablemente Samuel resolvió su problema hace mucho tiempo. Sin embargo, tuve el mismo problema y encontré esta publicación mientras navegaba por google. Encontré una solución y creo que vale la pena agregarla.

Puede usar el método de apagado en la clase de socket. Puede evitar más envíos, recepciones o ambos.

socket.shutdown (socket.SHUT_WR)

Lo anterior evita futuros envíos, como un ejemplo.

Consulte los documentos de Python para obtener más información.


Debo pedir disculpas por los comentarios a continuación. El comentario anterior de @Matt Anderson funciona. Cometí un error al probarlo, lo que me llevó a mi publicación a continuación.

Usar tiempo de espera no es una solución muy buena. Puede parecer que despertar por un instante y luego volver a dormir no es gran cosa, pero he visto que afecta en gran medida el rendimiento de una aplicación. Usted tiene una operación que en su mayor parte quiere bloquear hasta que haya datos disponibles y, por lo tanto, duerma para siempre. Sin embargo, si quiere abortar por alguna razón, como cerrar su aplicación, entonces el truco es cómo salir. Para enchufes, puede usar seleccionar y escuchar en dos enchufes. Tu primaria, y una parada especial. Sin embargo, crear el shutdown es un poco doloroso. Tienes que crearlo. Tienes que conseguir que el socket de escucha lo acepte. Tienes que hacer un seguimiento de ambos extremos de este tubo. Tengo el mismo problema con la clase Cola sincronizada. Sin embargo, al menos puede insertar un objeto ficticio en la cola para activar el get (). Sin embargo, esto requiere que el objeto ficticio no se vea como tus datos normales. A veces me gustaría que Python tuviera algo así como la API de Windows WaitForMultipleObjects.