文档章节

python的多人多功能聊天室

疯狂的小企鹅
 疯狂的小企鹅
发布于 2014/06/21 11:46
字数 899
阅读 241
收藏 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


© 著作权归作者所有

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

疯狂的小企鹅

粉丝 11
博文 42
码字总数 20243
作品 6
杭州
程序员
Python 聊天室 II(SimpleXMLRPCServer模块实现)

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

FuniK
2012/12/19
0
0
用Python开发你的第一款聊天软件

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

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

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

Python新世界
07/25
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

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JS:异步 - 面试惨案

为什么会写这篇文章,很明显不符合我的性格的东西,原因是前段时间参与了一个面试,对于很多程序员来说,面试时候多么的鸦雀无声,事后心里就有多么的千军万马。去掉最开始毕业干了一年的Jav...

xmqywx
今天
0
0
Win10 64位系统,PHP 扩展 curl插件

执行:1. 拷贝php安装目录下,libeay32.dll、ssleay32.dll 、 libssh2.dll 到 C:\windows\system32 目录。2. 拷贝php/ext目录下, php_curl.dll 到 C:\windows\system32 目录; 3. p...

放飞E梦想O
今天
0
0
谈谈神秘的ES6——(五)解构赋值【对象篇】

上一节课我们了解了有关数组的解构赋值相关内容,这节课,我们接着,来讲讲对象的解构赋值。 解构不仅可以用于数组,还可以用于对象。 let { foo, bar } = { foo: "aaa", bar: "bbb" };fo...

JandenMa
今天
1
0
OSChina 周一乱弹 —— 有人要给本汪介绍妹子啦

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子 :分享水木年华的单曲《中学时代》@小小编辑 手机党少年们想听歌,请使劲儿戳(这里) @须臾时光:夏天还在做最后的挣扎,但是晚上...

小小编辑
今天
21
5
centos7安装redis及开机启动

配置编译环境: sudo yum install gcc-c++ 下载源码: wget http://download.redis.io/releases/redis-3.2.8.tar.gz 解压源码: tar -zxvf redis-3.2.8.tar.gz 进入到解压目录: cd redis-3......

hotsmile
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部