[Python-es] ¿Como cierro correctamente un hilo-servidor de sockets?
Nekmo
contacto en nekmo.com
Sab Ago 27 04:39:56 CEST 2011
La mejor solución a mi parecer, es modificar el timeout. A parte, si
usáis TCP, a veces solo queda esperar a que se libere... es el
problema de dicho protocolo :P
Un cordial saludo:
-- Nekmo.
Sitio web: http://nekmo.com
Dirección de contacto: contacto en nekmo.com
XMPP/Jabber: contacto en nekmo.com
Identi.ca: http://identi.ca/nekmo
Diaspora: Nekmo
Google+: Nekmo Com
El día 26 de agosto de 2011 21:53, gerardo Juarez
<gerardojuarez en buyteknet.info> escribió:
> Efectivamente Sergio, es el mismo comportamiento que yo he observado: la
> aplicación cierra el socket, termina y aún así, pasan algunos segundos
> para que el puerto quede disponible nuevamente. No me parece que sea un
> problema directamente atribuible a tu aplicación, sino más bien a la
> forma en que el sistema libera -o registra- que los puertos han sido
> liberados. Habría que informarse cómo está implementada la función
> 'restart' de los servicios de Linux, por ejemplo, porque allí terminan
> un servicio y lo reinician tan pronto como es posible. De qué modo
> averiguan que ya está disponible el puerto?
>
> Sergio Martín wrote:
>>
>> Pero al cerrar el socket del servidor (como comento en mi segundo mensaje)
>> ¿no debería liberarse el puerto?
>> Por otro lado ¿como puedo cerrar el hilo si lo tengo en espera de un
>> cliente? ¿Hay alguna otra forma aparte de salir del bucle infinito que
>> tengo?
>>
>> El 26 de agosto de 2011 15:10, chakalinux <chakalinux en gmail.com
>> <mailto:chakalinux en gmail.com>> escribió:
>>
>> 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 <mailto: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 <mailto: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 <mailto:Python-es en python.org>
>> http://mail.python.org/mailman/listinfo/python-es
>> FAQ: http://python-es-faq.wikidot.com/
>>
>>
>>
>> _______________________________________________
>> Python-es mailing list
>> Python-es en python.org <mailto:Python-es en python.org>
>> http://mail.python.org/mailman/listinfo/python-es
>> FAQ: http://python-es-faq.wikidot.com/
>>
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> Python-es mailing list
>> Python-es en python.org
>> http://mail.python.org/mailman/listinfo/python-es
>> FAQ: http://python-es-faq.wikidot.com/
>>
>
>
> _______________________________________________
> Python-es mailing list
> Python-es en python.org
> http://mail.python.org/mailman/listinfo/python-es
> FAQ: http://python-es-faq.wikidot.com/
>
Más información sobre la lista de distribución Python-es