python 基础教程 24章 虚拟茶话会 async5

#/usr/bin/python
# *-* coding:utf-8 *-*


"""
多个聊天室的版本
转载自 https://bblove.me/2015/03/26/python-im/
"""


from asyncore import dispatcher
from asynchat import async_chat
import socket, asyncore


PORT = 5005
NAME = 'TestChat'


class EndSession(Exception): pass


class CommandHandler():
"""
类似于标准库中cmd.Cmd的简单命令处理程序
"""

#响应未知的命令
def unknown(self, session, cmd):
session.push('Unknown command: %s \r\n' % cmd)

def handle(self, session, line):
if not line.strip():
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 ChatRoom(CommandHandler):
def __init__(self, name, server):
self.server = server
self.name = name
self.sessions = []

def add(self, session):
self.broadcast(session.name + ' has entered the room %s\r\n' %self.name)
session.push('You can type "h" for help\r\n')
#因为后面要将用户挪动房间,所以必须保存每个用户的session,这样才能挪动和删除
self.server.users[session.name] = session
self.sessions.append(session)

def remove(self, session):
try:
self.sessions.remove(session)
except: pass #如果此处的session为空或者已经不存在,会出错,此处不上报

def broadcast(self, line):
#广播,只广播到当前房间
for session in self.sessions:
session.push(line)

def do_say(self, session, line):
#发言
self.broadcast(session.name + ':' + line + '\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.keys():
session.push('The name %s taken\r\n' % name)
session.push('Please try again\r\n')
else:
session.server.users[name] = session.server.users.pop(session.name)
session.name = name
session.enter(self)
self.do_list(session, '')
session.push('type "select name" to choose one room\r\n')

def do_logout(self, session, line):
'退出'
raise EndSession


def do_look(self, session, line):
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')

#查看当前所有的房间
def do_list(self, session, line):
session.push('The room list is below\r\n')
session.push('  '.join(self.server.rooms) + '\r\n')

#选择房间
def do_select(self, session, line):
name = line.strip()
if not name:
session.push('Please enter a name\r\n')
elif name in self.server.rooms.keys():
session.enter(self.server.rooms[name])
self.broadcast(' %s, Welcome to join %s\r\n' %(session.name, name))

#输出帮助
def do_h(self, session, line):
session.push('you can use this command: \r\n1, who to see who is on this server(online and offline)\r\n2,'
'list to see how many room are avaliable\r\n3, look to see who are in this room\r\n4,login to login online and'
'change a name\r\n5, create to create a new room\r\n')

#创建新房间
def do_create(self, session, line):
name = line.strip()
if not name:
session.push('Please enter a name\r\n')
elif name in self.server.rooms.keys():
session.push('The room name %s is taken\r\n' % name)
session.push('Please try again\r\n')
else:
ChatRoom(name, self.server)
session.server.rooms[name] = ChatRoom(name, self.server)
session.push('The room %s create successful\r\n' % name)
session.enter(session.server.rooms[name])


#每个用户会话类, 这是个重点类
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 = 'vistor' + str(len(server.users)) #初始化用户名,用vistor1之类表示
self.room = self.server.main_room
self.enter(self.server.main_room)

def enter(self, 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)




class ChatServer(dispatcher):


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.sesions = {}
self.name = name
self.users = {}
self.rooms = {}
#新建一个房间hall,因为每个初始登录的用户都没有房间,但是操作是依赖于ChatRoom类的,所以设置一个默认初始房间
self.main_room = ChatRoom('hall', self)
self.rooms[self.main_room.name] = self.main_room

def handle_accept(self):
conn, addr = self.accept()
ChatSession(self, conn)
print('Connection attempt from', addr[0])


if __name__ == '__main__':
print('Server Start')
s = ChatServer(PORT, NAME)
try:
asyncore.loop()
except KeyboardInterrupt: print('End Run')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值