Python asynchat Chat Example
- The handler.push method is thread-safe.
- The server implements broadcast to all the listening chat clients.
- Two chat clients implement send/read. This seemed easiest because Python doesn't have a simple way to do an asynchronous raw_input.
- Messages exchanged between client and server must be terminated by newlines.
chat_server.py
import asynchat import asyncore import socket chat_room = {} class ChatHandler(asynchat.async_chat): def __init__(self, sock): asynchat.async_chat.__init__(self, sock=sock, map=chat_room) self.set_terminator('\n') self.buffer = [] def collect_incoming_data(self, data): self.buffer.append(data) def found_terminator(self): msg = ''.join(self.buffer) print 'Received:', msg for handler in chat_room.itervalues(): if hasattr(handler, 'push'): handler.push(msg + '\n') self.buffer = [] class ChatServer(asyncore.dispatcher): def __init__(self, host, port): asyncore.dispatcher.__init__(self, map=chat_room) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.bind((host, port)) self.listen(5) def handle_accept(self): pair = self.accept() if pair is not None: sock, addr = pair print 'Incoming connection from %s' % repr(addr) handler = ChatHandler(sock) server = ChatServer('localhost', 5050) print 'Serving on localhost:5050' asyncore.loop(map=chat_room)
chat_client_send.py
import asynchat import asyncore import socket import threading class ChatClient(asynchat.async_chat): def __init__(self, host, port): asynchat.async_chat.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((host, port)) self.set_terminator('\n') self.buffer = [] def collect_incoming_data(self, data): pass def found_terminator(self): pass client = ChatClient('localhost', 5050) comm = threading.Thread(target=asyncore.loop) comm.daemon = True comm.start() while True: msg = raw_input('> ') client.push(msg + '\n')
chat_client_read.py
import asynchat import asyncore import socket class ChatClient(asynchat.async_chat): def __init__(self, host, port): asynchat.async_chat.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((host, port)) self.set_terminator('\n') self.buffer = [] def collect_incoming_data(self, data): self.buffer.append(data) def found_terminator(self): msg = ''.join(self.buffer) print 'Received:', msg self.buffer = [] client = ChatClient('localhost', 5050) print 'Listening on localhost:5050' asyncore.loop()