python的多人多功能聊天室

从Beginning Python: From Novice to Professional, Second Edition 中的一个chatroom项目中拿出来的。那里的聊天室,只有一个单间聊天室功能,使用asyncore和asynchat实现,只能群聊。后来我给它加上了多人聊天室功能。还加上了私聊等功能。改用twisted实现并把它变成了守护模式(使用twistd)

命令列表:

/login username [roomname]

/who 查看当前登录的用户

/look 查看在当前聊天房间的用户

/to username content 私信用户

/exit 退出当前聊天房间

/logout 退出聊天服务器


代码如下:

from twisted.internet import reactor
from twisted.internet.protocol import Protocol,Factory
from twisted.internet import defer
from twisted.protocols.basic import LineReceiver
from twisted.application import internet,service
from twisted.python import log


class commaneHandler:
    def handle(self,session,line):
        if not line.strip():return
        parts=line.split(' ',1)
        cmd=parts[0].strip()
        try:
            if cmd[0]!='/':
                cmd="/say"
                line=line.strip()
            else:
                line=parts[1].strip()
        except IndexError:
            line=""
        finally:
            cmd=cmd[1:].strip()

        meth=getattr(self,"do_"+cmd,None)
        try:
            meth(session,line)
        except TypeError:
            self.unknow(session,cmd)

    def unknow(self,session,cmd):
        session.write("%s:unknow command!\n"%cmd)

                
class Room(commaneHandler):
    def __init__(self,server,name=""):
        self.server=server
        self.roomName=name
        self.sessions=[]

    def add(self,session):
        self.sessions.append(session)

    def remove(self,session):
        self.sessions.remove(session)

    def broadcast(self,line):
        for session in self.sessions:
            session.write(line+'\n')
    
    def do_list(self,session,line):
        session.write("list for ChatRoom\n")
        for room in self.server.rooms:
            session.write(room+'\n')
    
    def do_logout(self,session,line):
        session.entry(LogoutRoom(self.server))
        session.d.errback("")

class LoginRoom(Room):
    def add(self,session):
        Room.add(self,session)
        log.msg("Connection from %s "%session.session.getPeer())
        session.write("Welcome to ChatTest for twisted v1.1!\n")
    def do_login(self,session,line):
        parts=line.strip().split(" ")
        name=parts[0]
        if not name:
            session.write("Please entry a name\n")
        elif name in self.server.users:
            session.write("The name %s is token\n"%name)
        else:
            session.name=name
            try:
                roomName=parts[1]
            except IndexError:
                roomName="main"
            
            if not roomName in self.server.rooms:
                self.server.createRoom(roomName)
            session.entry(self.server.rooms[roomName])
    
    def unknow(self,session,line):
        session.write("Commands:login logout list\n")

class LogoutRoom(Room):
    def add(self,session):
        try:
            del self.server.users[session.name]
        except KeyError:
            pass

class ChatRoom(Room):
    def add(self,session):
        session.write("Welcome to ChatRoom:%s !\n"%self.roomName)
        mess=session.name+" has join the room"
        self.broadcast(mess)
        log.msg(mess)
        Room.add(self,session)
        self.server.users[session.name]=session
    
    def remove(self,session):
        Room.remove(self,session)
        self.broadcast(session.name+" has left the room")
        
    def do_say(self,session,line):
        self.broadcast("%s: %s"%(session.name,line))

    def do_look(self,session,line):
        session.write("list for room:\n")
        for i,other in enumerate(self.sessions):
            session.write("%d: %s\n"%(i,other.name))

    def do_exit(self,session,line):
        try:
            del self.server.users[session.name]
        except KeyError:
            pass
        session.entry(LoginRoom(self.server))

    def do_to(self,session,line):
        try:
            parts=line.split(' ',1)
            name=parts[0]
            line=parts[1]
            toUser=self.server.users[name]
            toUser.write("%s: %s\n"%(session.name,line))
        except IndexError:
            session.write("Usage:/to toUser line\n")
            return False
        except KeyError:
            session.write("%s does not exist!\n"%name)
            return False
        
    def do_who(self,session,line):
        session.write("list for server:\n")
        for i,name in enumerate(self.server.users.keys()):
            session.write("%d: %s\n"%(i,name))

class chatSession:
    def __init__(self,server,session,d):
        self.d=d
        self.server=server
        self.session=session
        self.name=None
        self.entry(LoginRoom(self.server,""))

    def write(self,line):
        self.session.write(line)

    def entry(self,room):
        try:
            cur=self.room
        except AttributeError:
            pass
        else:
            cur.remove(self)
        self.room=room
        room.add(self)

    def execComm(self,line):
        self.room.handle(self,line.strip())

class ChatProtocol(LineReceiver):
    
    def connectionMade(self):
        d=defer.Deferred()
        d.addBoth(self.endSession)
        self.s=chatSession(self.factory,self.transport,d)
    
    def endSession(self,_):
        self.transport.loseConnection()

    def connectionLost(self,reason):
        pass
    
    def connectionFailure(self,connector,reason):
        print reason


    def lineReceived(self,line):
        self.s.execComm(line)

class ChatFactory(Factory):
    protocol=ChatProtocol
    def __init__(self):
        self.users={}
        self.rooms={}
        self.createRoom("main")

    def createRoom(self,name):
        self.rooms[name]=ChatRoom(self,name)
        
port=1234
iface="localhost"
application=service.Application("chatRoom")
top_service=service.MultiService()
factory=ChatFactory()
tcp_service=internet.TCPServer(port,factory,
        interface=iface)
tcp_service.setServiceParent(top_service)
top_service.setServiceParent(application)

输出:

ljd&11:44:51:py$ twistd -n -y tw_chatRoom.py 

2014-06-21 11:45:01+0800 [-] Log opened.

2014-06-21 11:45:01+0800 [-] twistd 11.1.0 (/usr/bin/python 2.7.3) starting up.

2014-06-21 11:45:01+0800 [-] reactor class: twisted.internet.pollreactor.PollReactor.

2014-06-21 11:45:01+0800 [-] ChatFactory starting on 1234

2014-06-21 11:45:01+0800 [-] Starting factory <__builtin__.ChatFactory instance at 0xfe6368>

2014-06-21 11:45:09+0800 [__builtin__.ChatFactory] Connection from IPv4Address(TCP, '127.0.0.1', 58755) 

2014-06-21 11:45:23+0800 [ChatProtocol,0,127.0.0.1] abc has join the room


你可能感兴趣的:(python的多人多功能聊天室)