Sala de chat con el módulo asyncore

El módulo estándar asyncore provee una simple interfaz para escribir servidores y clientes que trabajen de manera sincrónica. De este modo, un servidor puede albergar gran cantidad de clientes y responder a cada uno de ellos al mismo tiempo.

Código de fuente de un cliente y un servidor que constituyen a una sala de chat, en donde los clientes reciben los mensajes en tiempo real. Para cerrar la conexión, tipear «salir» (sin comillas).

Descargar código de fuente: asyncorechat.zip

client.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#       client.py
#       
#       Copyright 2013 Recursos Python - www.recursospython.com
#       
#

import asyncore
from socket import AF_INET, SOCK_STREAM
from threading import Thread


class TCPClient(asyncore.dispatcher_with_send):
    
    def __init__(self, host=("localhost", 6000)):
        asyncore.dispatcher_with_send.__init__(self)
        self.create_socket(AF_INET, SOCK_STREAM)
        self.connect(host)
        
        Thread(target=self.sender).start()  # Nuevo hilo
    
    def sender(self):
        # Enviar los mensajes desde un hilo aparte,
        # para que en paralelo se sigan reciban los
        # mensajes del servidor.
        while True:
            data = raw_input("\n")
            if data:
                if data.lower() == "salir":
                    break
                else:
                    self.sendall(data)
            else:
                print "Debes escribir un mensaje."
        self.handle_close()
    
    def handle_connect(self):
        print "Has entrado al chat."
    
    def handle_close(self):
        print "Has salido del chat."
        self.close()
    
    def handle_read(self):
        """Imprimir los mensajes"""
        print self.recv(1024)


if __name__ == "__main__":
    client = TCPClient()
    asyncore.loop()

server.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#       server.py
#       
#       Copyright 2013 Recursos Python - www.recursospython.com
#       
#

import asyncore
from socket import AF_INET, SOCK_STREAM


# Diccionario para cada uno de los clientes.
# No es lo más recomendado usar variables globales.
clients = {}

class TCPHandler(asyncore.dispatcher_with_send):
    
    def __init__(self, conn):
        asyncore.dispatcher_with_send.__init__(self, conn)
        self.addr = "%s:%d" % self.addr
    
    def handle_read(self):
        """Enviar el mensaje recibido a cada uno de los clientes"""
        data = self.recv(1024)
        if data:
            for client in clients:
                clients[client].send("%s dice: %s" % (self.addr, data))
    
    def handle_close(self):
        print self.addr + " se ha desconectado."
        del clients[self.addr]
        self.close()


class TCPServer(asyncore.dispatcher):

    def __init__(self, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(AF_INET, SOCK_STREAM)
        self.set_reuse_addr()
        self.bind(("localhost", port))
        self.listen(20)

    def handle_accept(self):
        client = self.accept()
        if client is not None:
            conn, addr = client
            handler = TCPHandler(conn)
            clients[handler.addr] = handler
            print handler.addr + " se ha conectado."


if __name__ == "__main__":
    server = TCPServer(6000)
    asyncore.loop()

Curso online 👨‍💻

¡Ya lanzamos el curso oficial de Recursos Python en Udemy! Un curso moderno para aprender Python desde cero con programación orientada a objetos, SQL y tkinter en 2024.

Consultoría 💡

Ofrecemos servicios profesionales de desarrollo y capacitación en Python a personas y empresas. Consultanos por tu proyecto.

1 comentario.

Deja una respuesta