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.
larson says:
solo en la version 2 de python funciona bien ya en la 3 da un error tras otro