📄 listing24-6.py
字号:
from asyncore import dispatcherfrom asynchat import async_chatimport socket, asyncorePORT = 5005NAME = 'TestChat'class EndSession(Exception): passclass CommandHandler: """ Simple command handler similar to cmd.Cmd from the standard library. """ def unknown(self, session, cmd): 'Respond to an unknown command' session.push('Unknown command: %s\r\n' % cmd) def handle(self, session, line): 'Handle a received line from a given session' if not line.strip(): return # Split off the command: parts = line.split(' ', 1) cmd = parts[0] try: line = parts[1].strip() except IndexError: line = '' # Try to find a handler: meth = getattr(self, 'do_'+cmd, None) try: # Assume it's callable: meth(session, line) except TypeError: # If it isn't, respond to the unknown command: self.unknown(session, cmd)class Room(CommandHandler): """ A generic environment that may contain one or more users (sessions). It takes care of basic command handling and broadcasting. """ def __init__(self, server): self.server = server self.sessions = [] def add(self, session): 'A session (user) has entered the room' self.sessions.append(session) def remove(self, session): 'A session (user) has left the room' self.sessions.remove(session) def broadcast(self, line): 'Send a line to all sessions in the room' for session in self.sessions: session.push(line) def do_logout(self, session, line): 'Respond to the logout command' raise EndSessionclass LoginRoom(Room): """ A room meant for a single person who has just connected. """ def add(self, session): Room.add(self, session) # When a user enters, greet him/her: self.broadcast('Welcome to %s\r\n' % self.server.name) def unknown(self, session, cmd): # All unknown commands (anything except login or logout) # results in a prodding: session.push('Please log in\nUse "login <nick>"\r\n') def do_login(self, session, line): name = line.strip() # Make sure the user has entered a name: if not name: session.push('Please enter a name\r\n') # Make sure that the name isn't in use: elif name in self.server.users: session.push('The name "%s" is taken.\r\n' % name) session.push('Please try again.\r\n') else: # The name is OK, so it is stored in the session, and # the user is moved into the main room. session.name = name session.enter(self.server.main_room)class ChatRoom(Room): """ A room meant for multiple users who can chat with the others in the room. """ def add(self, session): # Notify everyone that a new user has entered: self.broadcast(session.name + ' has entered the room.\r\n') self.server.users[session.name] = session Room.add(self, session) def remove(self, session): Room.remove(self, session) # Notify everyone that a user has left: self.broadcast(session.name + ' has left the room.\r\n') def do_say(self, session, line): self.broadcast(session.name+': '+line+'\r\n') def do_look(self, session, line): 'Handles the look command, used to see who is in a room' session.push('The following are in this room:\r\n') for other in self.sessions: session.push(other.name + '\r\n') def do_who(self, session, line): 'Handles the who command, used to see who is logged in' session.push('The following are logged in:\r\n') for name in self.server.users: session.push(name + '\r\n')class LogoutRoom(Room): """ A simple room for a single user. Its sole purpose is to remove the user's name from the server. """ def add(self, session): # When a session (user) enters the LogoutRoom it is deleted try: del self.server.users[session.name] except KeyError: passclass ChatSession(async_chat): """ A single session, which takes care of the communication with a single user. """ def __init__(self, server, sock): async_chat.__init__(self, sock) self.server = server self.set_terminator("\r\n") self.data = [] self.name = None # All sessions begin in a separate LoginRoom: self.enter(LoginRoom(server)) def enter(self, room): # Remove self from current room and add self to # next room... try: cur = self.room except AttributeError: pass else: cur.remove(self) self.room = room room.add(self) def collect_incoming_data(self, data): self.data.append(data) def found_terminator(self): line = ''.join(self.data) self.data = [] try: self.room.handle(self, line) except EndSession: self.handle_close() def handle_close(self): async_chat.handle_close(self) self.enter(LogoutRoom(self.server))class ChatServer(dispatcher): """ A chat server with a single room. """ def __init__(self, port, name): dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind(('', port)) self.listen(5) self.name = name self.users = {} self.main_room = ChatRoom(self) def handle_accept(self): conn, addr = self.accept() ChatSession(self, conn)if __name__ == '__main__': s = ChatServer(PORT, NAME) try: asyncore.loop() except KeyboardInterrupt: print
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -