python tornado websocket 多聊天室(返回消息给部分连接者)

python tornado 构建多个聊天室, 多个聊天室之间相互独立, 实现服务器端将消息返回给相应的部分客户端!

chatHome.py    // 服务器端, 渲染主页 --》 聊天室建立websocket连接 --》 服务器端记录连接 --》 服务器端接收消息,判断聊天室,返回最新消息到对应聊天室

 #-*-coding:utf-8-*-
__author__ = 'zhouwang'
import json
import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import tornado.options
from uuid import uuid4 class ChatHome(object):
'''
处理websocket 服务器与客户端交互
'''
chatRegister = {} def register(self, newer):
'''
保存新加入的客户端连接、监听实例,并向聊天室其他成员发送消息!
'''
home = str(newer.get_argument('n')) #获取所在聊天室
if home in self.chatRegister:
self.chatRegister[home].append(newer)
else:
self.chatRegister[home] = [newer] message = {
'from': 'sys',
'message': '%s 加入聊天室(%s)' % (str(newer.get_argument('u')), home)
}
self.callbackTrigger(home, message) def unregister(self, lefter):
'''
客户端关闭连接,删除聊天室内对应的客户端连接实例
'''
home = str(lefter.get_argument('n'))
self.chatRegister[home].remove(lefter)
if self.chatRegister[home]:
message = {
'from': 'sys',
'message': '%s 离开聊天室(%s)' % (str(lefter.get_argument('u')), home)
}
self.callbackTrigger(home, message) def callbackNews(self, sender, message):
'''
处理客户端提交的消息,发送给对应聊天室内所有的客户端
'''
home = str(sender.get_argument('n'))
user = str(sender.get_argument('u'))
message = {
'from': user,
'message': message
}
self.callbackTrigger(home, message) def callbackTrigger(self, home, message):
'''
消息触发器,将最新消息返回给对应聊天室的所有成员
'''
for callbacker in self.chatRegister[home]:
callbacker.write_message(json.dumps(message)) class chatBasicHandler(tornado.web.RequestHandler):
'''
主页, 选择进入聊天室
'''
def get(self, *args, **kwargs):
session = uuid4() #生成随机标识码,代替用户登录
self.render('chat/basic.html', session = session) class homeHandler(tornado.web.RequestHandler):
'''
聊天室, 获取主页选择聊天室跳转的get信息渲染页面
'''
def get(self, *args, **kwargs):
n = self.get_argument('n') #聊天室
u = self.get_argument('u') #用户
self.render('chat/home.html', n=n, u=u) class newChatStatus(tornado.websocket.WebSocketHandler):
'''
websocket, 记录客户端连接,删除客户端连接,接收最新消息
'''
def open(self):
n = str(self.get_argument('n'))
self.write_message(json.dumps({'from':'sys', 'message':'欢迎来到 聊天室(%s)' % n})) #向新加入用户发送首次消息
self.application.chathome.register(self) #记录客户端连接 def on_close(self):
self.application.chathome.unregister(self) #删除客户端连接 def on_message(self, message):
self.application.chathome.callbackNews(self, message) #处理客户端提交的最新消息 class Application(tornado.web.Application):
def __init__(self):
self.chathome = ChatHome() handlers = [
(r'/', chatBasicHandler),
(r'/home/', homeHandler),
(r'/newChatStatus/', newChatStatus),
] settings = {
'template_path': 'html',
'static_path': 'static'
} tornado.web.Application.__init__(self, handlers, **settings) if __name__ == '__main__':
tornado.options.parse_command_line()
server = tornado.httpserver.HTTPServer(Application())
server.listen(8000)
tornado.ioloop.IOLoop.instance().start()

basic.html    //主页, 选择进入聊天室, sessoin 设定为登录用户, GET: n指定聊天室, u指定用户

 <body>
<h1>你好 !{{ session }} <br> 欢迎来到聊天室!</h1>
<a href="/home/?n=1&u={{ session }}"> 聊天室一 </a> &nbsp; <a href="/home/?n=2&u={{ session }}"> 聊天室二 </a>
</body>

home.html         //聊天室,建立websocket连接,发送消息,接受消息,根据最新消息的发送者处理消息格式并写入页面

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="http://libs.baidu.com/jquery/1.10.2/jquery.min.js"></script>
<script>
$(function(){
n = $("#n").val()
u = $("#u").val() $("#btn").click(function(){
sendText()
})
function requestText(){
host = "ws://localhost:8000/newChatStatus/?n=" + n + "&u=" +u
websocket = new WebSocket(host) websocket.onopen = function(evt){} // 建立连接
websocket.onmessage = function(evt){ // 获取服务器返回的信息
data = $.parseJSON(evt.data)
if(data['from']=='sys'){
$('#chatinfo').append("<p style='width: 100%; text-align:center; font-size: 16px; color: green'>" + data['message'] + "</p>");
}else if(data['from']==u){
$('#chatinfo').append("<p style='width: 100%; text-align:right; font-size:15px'>" + u + ": <br>" +"<span style='color: blue'>" + data['message'] + "</span>" + "</p>");
}else{
$('#chatinfo').append("<p style='width: 100%; text-align:left; font-size:15px'>" + data['from'] + ": <br>" +"<span style='color: red'>" + data['message'] + "</span>" + "</p>");
} }
websocket.onerror = function(evt){}
} requestText() // 开始 websocket function sendText(){ // 向服务器发送信息
websocket.send($("#chat_text").val())
}
}) </script>
</head>
<body>
<div align="center">
<div style="width: 70%">
<h1>聊天室({{ n }})!</h1>
<input type="hidden" value="{{ n }}" id="n">
<input type="hidden" value="{{ u }}" id="u"> <div id="chatinfo" style="padding:10px;border: 1px solid #888">
<!-- 聊天内容 -->
</div> <div style="clear: both; text-align:right; margin-top: 20px">
<input type="text" name="chat_text" id="chat_text">
<button id="btn">发送</button>
</div>
</div>
</div>
</body>
</html>
上一篇:NuGet学习笔记3——搭建属于自己的NuGet服务器


下一篇:不用webservice wcf提供服务,用Rest更轻量