[Python-es] ¿Como cierro correctamente un hilo-servidor de sockets?

Sergio Martín sergiomartinj en gmail.com
Vie Ago 26 20:25:43 CEST 2011


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> 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>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/
>>
>
>
> _______________________________________________
> 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/734bc4d9/attachment.html>


Más información sobre la lista de distribución Python-es