文档章节

python的多人多功能聊天室

疯狂的小企鹅
 疯狂的小企鹅
发布于 2014/06/21 11:46
字数 899
阅读 255
收藏 1

从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


© 著作权归作者所有

共有 人打赏支持
疯狂的小企鹅

疯狂的小企鹅

粉丝 12
博文 42
码字总数 20243
作品 6
杭州
程序员
私信 提问
用Python开发你的第一款聊天软件

在本实验中,我们将实现一个简单的图形界面聊天系统。我们可以通过图形客户端登录聊天室,并与其他成员进行聊天。 本教程由实验楼120发布在实验楼,完整教程、代码及在线练习地址:Python 实...

实验楼
07/16
0
0
利用Python打造一个多人在线匿名聊天的小程序!(前后端完整开发)

最近看到好多设计类网站, 都提供了多人在线匿名聊天的小功能, 感觉很有意思, 于是自己就用django框架写了一个, 支持手动实时更名, 最下方提供了完整的源码. 在线聊天(不需要登录,开一个窗口,...

Python新世界
07/25
0
0
Python 聊天室 II(SimpleXMLRPCServer模块实现)

并不是上一个用SocketServer的聊天室的延续。用远程调用完成的聊天室。 正好有Java的RMI聊天室的作业,就先用Python写了一个简单的类似远程调用的东西,逻辑完成之后,在Java上写一遍也是水到...

FuniK
2012/12/19
0
0
python的多路复用实现聊天群

在我的《python高级编程和异步io编程》中我讲解了socket编程,这里贴一段用socket实现聊天室的功能的源码,因为最近工作比较忙,后期我会将这里的代码细节分析出来,目前先把代码贴上。大家自...

__bobby
06/30
0
0
《 Head First 》学习笔记:观察者模式 (python实现)

病殃殃的还是来记录一下学习笔记,不然的话过几天可能就忘了,白学了。 observer mode 在java 用得很多,咱也试一下用python来实现,由于python没有接口,就只能继承一个类来用用了。 先撸一...

Jbryan
2013/06/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

RestClientUtil和ConfigRestClientUtil区别说明

RestClientUtil directly executes the DSL defined in the code. ConfigRestClientUtil gets the DSL defined in the configuration file by the DSL name and executes it. RestClientUtil......

bboss
40分钟前
6
0

中国龙-扬科
昨天
2
0
Linux系统设置全局的默认网络代理

更改全局配置文件/etc/profile all_proxy="all_proxy=socks://rahowviahva.ml:80/"ftp_proxy="ftp_proxy=http://rahowviahva.ml:80/"http_proxy="http_proxy=http://rahowviahva.ml:80/"......

临江仙卜算子
昨天
8
0
java框架学习日志-6(bean作用域和自动装配)

本章补充bean的作用域和自动装配 bean作用域 之前提到可以用scope来设置单例模式 <bean id="type" class="cn.dota2.tpye.Type" scope="singleton"></bean> 除此之外还有几种用法 singleton:......

白话
昨天
8
0
在PC上测试移动端网站和模拟手机浏览器的5大方法

总结很全面,保存下来以备不时之需。原文地址:https://www.cnblogs.com/coolfeng/p/4708942.html

kitty1116
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部