[Python-es] ¿Como cierro correctamente un hilo-servidor de sockets?
chakalinux
chakalinux en gmail.com
Vie Ago 26 15:10:57 CEST 2011
En la interrupcion KeyboardInterrupt tienes que cerrar los hilos para que no
se te quede el mismo en CLOSE_WAIT que en ciertos casos puede durar bastante
en liberarse.
De todas maneras yo te recomiendo que uses la librería select o asyncore
para manejar socket's, intenta evitar cuando puedas sockets y threading
El 26 de agosto de 2011 02:21, Sergio Martín <sergiomartinj en gmail.com>escribió:
> Comentar que aunque añada la línea:
> self.socketserver.close()
> en el método close() de la clase TelnetServer el resultado es el mismo.
>
> El día 26 de agosto de 2011 02:17, Sergio Martín
> <sergiomartinj en gmail.com> escribió:
> > Tengo un script en el que, primero, ejecuto un servidor de sockets en
> > un hilo, y cada conexión que reciba, genera su propio hilo.
> > El problema viene cuando intento salirme del programa mediante una
> > excepción KeyboardInterrupt controlada, funciona bien si no ha habido
> > ninguna conexión al socket-servidor, pero si me salgo del programa una
> > vez que he recibido alguna conexión, y, a continuación ejecuto el
> > programa de nuevo, me sale un "socket.error: [Errno 48] Address
> > already in use", como si no hubiese cerrado el socket del servidor
> > correctamente, teniéndome que esperar un rato hasta que se libere el
> > puerto.
> > Tengo controladas dos situaciones una que desde el cliente telnet se
> > pase el comando "quit", con lo que cierro el socket del cliente, y
> > otra cuando se pierde la conexión con el cliente sin introducir el
> > comando "quit"
> > El error solo me lo lanza cuando he salido por medio del "quit".
> >
> > Aviso que está escrito en python3, y se que hay mejores formas de
> > hacer esto en vez de usar hilos, como el módulo twisted (sin
> > compatibilidad python3) o el asyncore, pero solo tengo planeado
> > recibir un par de conexiones simultáneas por lo que no se generarán
> > muchos hilos.
> >
> > Pongo una versión simplificada del programa, con solo lo básico para
> > ilustrar el problema:
> >
> > #! /usr/bin/env python3
> >
> > import threading
> > import socket
> > import sys
> > import time
> >
> > class TelnetServer(threading.Thread):
> >
> > def __init__(self):
> > threading.Thread.__init__(self)
> > self.socketserver = socket.socket()
> > self.socketserver.bind(('', 9999))
> > self.socketserver.listen(5)
> >
> > def run(self):
> > print('Servidor en marcha')
> > while True:
> > socketclient, addr = self.socketserver.accept()
> > client = TelnetClient(socketclient, addr)
> > client.start()
> >
> > def close(self):
> > print('Servidor detenido')
> >
> > class TelnetClient(threading.Thread):
> >
> > def __init__(self, socketclient, addr):
> > threading.Thread.__init__(self)
> > self.socketclient = socketclient
> > self.addr = addr
> >
> > def run(self):
> > print('Conexión: %s:%s' % (self.addr[0], self.addr[1]))
> > while True:
> > try:
> > command, args = self.prompt()
> > except socket.error:
> > self.close()
> > break
> >
> > if command == None:
> > pass
> > elif command == 'quit':
> > self.close()
> > break
> > else:
> > self.send('Comando desconocido\n')
> >
> > def send(self, msg):
> > self.socketclient.send(msg.encode('utf8'))
> >
> > def recv(self):
> > return self.socketclient.recv(1024).decode('utf8')[:-2]
> >
> > def prompt(self):
> > try:
> > self.send('prompt> ')
> > recv_list = self.recv().split()
> > return recv_list[0].lower(), recv_list[1:]
> > except IndexError:
> > return None, []
> >
> > def close(self):
> > self.socketclient.close()
> > print('Desconexión: %s:%s' % (self.addr[0], self.addr[1]))
> >
> > if __name__ == '__main__':
> > try:
> > telnetserver = TelnetServer()
> > telnetserver.daemon = True
> > telnetserver.start()
> >
> > while True:
> > time.sleep(100)
> >
> > except KeyboardInterrupt:
> > telnetserver.close()
> > sys.exit()
> >
> _______________________________________________
> Python-es mailing list
> Python-es en python.org
> http://mail.python.org/mailman/listinfo/python-es
> FAQ: http://python-es-faq.wikidot.com/
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20110826/a86bad27/attachment.html>
Más información sobre la lista de distribución Python-es