总的来说是一个只支持一个聊天室的服务器端 客户端使用telnet
书籍下载地址:Python资料汇总
Python教程 这里是第二十四章的源码,练习研究之用
#coding:utf8 #python2.7 chatSer2.py #稍微复杂一点的聊天室服务器 ''' 用python启动服务 telnet连接之后就可以变成简单的聊天服务器 第一次登陆:login name 登出: logout 说话: say 查看谁登陆过服务器:who 查看同一个房间的人 : look 简单例子: telnet localhost 50005 Welcome to TestChat login tianshi diyu has entered the room. nih Unknown command: ih say nihao tianshi: nihao diyu: niyehao ''' from asyncore import dispatcher from asynchat import async_chat import socket import asyncore HOST = '' PORT = 50005 SERVERCONF = (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'