總的來說是一個只支援一個聊天室的伺服器端 用戶端使用telnet
書籍:Python資料匯總
Python教程 這裡是第二十四章的源碼,練習研究之用
#coding:utf8 #python2.7 chatSer2.py#稍微複雜一點的聊天室伺服器'''用python啟動服務 telnet串連之後就可以變成簡單的聊天伺服器第一次登陸:login name 登出: logout說話: say 查看誰登陸過伺服器:who 查看同一個房間的人 : look 簡單例子:telnet localhost 50005Welcome to TestChatlogin tianshidiyu has entered the room.nihUnknown command: ihsay nihaotianshi: nihaodiyu: niyehao'''from asyncore import dispatcher from asynchat import async_chatimport socketimport asyncoreHOST = ''PORT = 50005SERVERCONF = (HOST,PORT)NAME = 'TestChat'class EndSession(Exception): pass class CommandHandler(object): ''' 命令解析類 ''' def unknown(self,session,cmd): '響應未知的命令' session.push('Unknown command:%s \r\n' %cmd) def handle(self,session,line): '處理從用戶端發來的資訊 解析命令和內容' if not line: print 'please write a command...' if not line.strip(): print 'get a line :',line return parts = line.split(' ',1) #命令分離 cmd = parts[0] try: line = parts[1].strip() except IndexError: line = '' #調用相應的方法處理命令 meth = getattr(self, 'do_'+cmd, None) try: #調用命令對應的方法 meth(session,line) except TypeError: self.unknown(session, cmd) class Room(CommandHandler): ''' 包括一個或多個使用者(會話)的泛型環境。負責處理基本的命令和廣播 ''' def __init__(self,server): self.server = server self.sessions = [] def add(self, session): 'add a user' self.sessions.append(session) def remove(self,session): 'a user leave' self.sessions.remove(session) def broadcast(self,line): 'give all session in the room a line' for session in self.sessions: session.push(line) def do_logout(self,session,line): '響應登出命令' raise EndSession class LoginRoom(Room): ''' 為剛剛登陸的使用者準備的房間 ''' def add(self,session): Room.add(self, session) self.broadcast('Welcome to %s \r\n' %self.server.name) def unknown(self, session, cmd): session.push('Please login \nUse "login <nick>"\r\n') def do_login(self, session, line): name = line.strip() #登陸時必須指定一個使用者名稱 if not name: session.push('Please enter a name\r\n') elif name in self.server.users: #使用者名稱不可重複 ? session.push('The name "%s" is taken! \r\n' %name) session.push('Please try again.\r\n') else: session.name = name session.enter(self.server.main_room) class ChatRoom(Room): ''' 為多使用者在一起聊天準備的房間 ''' def add(self, session): #tell all new one come 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) #tell all the user logout 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): 'look who is in the 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): '查看誰登陸過' session.push('The following are logged in: \r\n') for name in self.server.users: session.push(name+ '\r\n')class LogoutRoom(Room): ''' 為單個使用者準備的房間,只用於將使用者從伺服器移除 ''' def add(self, session): try: del self.server.users[session.name] except KeyError: pass class ChatSession(async_chat): ''' 單個會話,負責和使用者通訊 ''' def __init__(self, server, sock): async_chat.__init__(self, sock) self.server = server self.set_terminator('\r\n') self.data = [] self.name = None #所有會話從這裡登入 self.enter(LoginRoom(server)) def enter(self, room): try: cur = self.room except AttributeError: pass 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): ''' 只有一個房間的聊天伺服器 ''' def __init__(self, serverconf, name): dispatcher.__init__(self) self.create_socket(socket.AF_INET,socket.SOCK_STREAM) self.set_reuse_addr() #可以重用上一次的連接埠號碼 self.bind(SERVERCONF) 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(SERVERCONF,NAME) try: asyncore.loop() except KeyboardInterrupt: print 'server Exception ...quit'
結果