[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