tornado-websocket
WebSockets 允许浏览器和服务器之间进行 双向通信
server端:
class WebSocketHandler(WebBaseHandler):
''' websocket '''
users = {} # {u'liubei': <handlers.message.message_handler.WebSocketHandler object at 0xb620b34c>,
# u'rock': <handlers.message.message_handler.WebSocketHandler object at 0xb61794ec>} # ------------------提高部分 开始------------------
# 提高部分只是细分发送信息的对象,不是很重要。完成提高部分结束后的 open,on_message, on_close即可。
@classmethod
def send_system_message(cls, self, content, send_type):
"""
:param self: 继承过websocket的base类的实例化对象,主要是self初始化了操作redis,mysql以及user对象的属性
:param content: 储存进redis的list data
:param send_type: 发送的类型(发给boss,ceo,员工...),由前端传过来
:return: 系统消息,发送给每个人
"""
target = 'system'
redis_msg = cls.dict_to_json(self, content, send_type, target)
self.conn.rpush('message:%s' % send_type, redis_msg) for f, v in WebSocketHandler.users.items():
v.write_message(redis_msg) @classmethod
def dict_to_json(cls, self, content, send_type, target):
"""
:param self: 继承过websocket的base类的实例化对象,主要是self初始化了操作redis,mysql以及user对象的属性
:param content: 储存进redis的list data
:param send_type: 发送的类型(发给boss,ceo,员工...),由前端传过来
:param target: 相当与用来区分缓存key的名字,比如 key_name="cache_list:%s"%target1, ...取对应分类的历史数据
:return:
"""
msg = {
"content": content,
"send_type": send_type,
"sender": self.current_user.name,
"target": target,
"datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
return tornado.escape.json_encode(msg) @classmethod
def send_role_message(cls, self, content, send_type, roleid):
"""
:param self:
:param content:
:param send_type:
:param roleid: 通过角色id,反查出属于该角色id的用户
:return: 发送信息给 该角色的所用用户
"""
role = Role.by_id(roleid)
redis_msg = cls.dict_to_json(self, content, send_type, role.name)
self.conn.rpush('message:%s' % send_type, redis_msg)
role_users = role.users # [zhangsan, lishi , wangwu] [zhangsan, lishi]
for user in role_users:
if WebSocketHandler.users.get(user.name, None) is not None: # user.name ['rock':self]
WebSocketHandler.users[user.name].write_message(redis_msg)
else:
# self.conn.lpush("ws:role_off_line",message)
pass @classmethod
def send_user_message(cls, self, content, send_type, user):
"""
:param self:
:param content:
:param send_type:
:param user: 发送的对象
:return: 发送信息给改用户 user
"""
redis_msg = cls.dict_to_json(self, content, send_type, user) self.conn.rpush('message:%s' % send_type, redis_msg)
self.conn.rpush('message:%s' % user, redis_msg) # 为了显示未读消息条数 if cls.users.get(user, None) is not None:
cls.users[user].write_message(redis_msg)
else:
# self.conn.lpush("ws:user_off_line",message)
pass # ------------------提高部分 结束------------------ def open(self):
'''
有用户进来后,存储该用户 {usernaem: self} self是每个登录用户的实例化类
(用该实例化对象发送是那个消息)
'''
WebSocketHandler.users[self.current_user.name] = self
pass def on_message(self, message): # 改方法获取消息,前端通过 ws对象.send(msg)发送
# print message # {"content_html":"聊天框输入的内容"} json
# {"content_html":"afaf<img src=\"/static/images/face/nm_thumb.gif\" title=\"[怒骂]\">"}
msg = tornado.escape.json_decode(message) # 解码 json字符串 --> 字符串
msg.update({
"name": self.current_user.name,
"datetime": datetime.now().strftime("%Y-%m-%d %H-%M-%S")
}) message = tornado.escape.json_encode(msg) # 转成json self.conn.rpush('message:list', message) # 存储消息为了显示历史消息 # self.write_message(msg) # 就算不转成json,write_message也能自己编码 # WebSocketHandler.users['liubei'].write_message(message) # 这是将不管谁的message只发给用户liubei for f, v in WebSocketHandler.users.items():
v.write_message(message) def on_close(self):
pass
前端:和后端一样,都需要完成open,on_message,on_close三个方法
<script type="text/javascript">
$(document).ready(function(){
//与服务器建立websocket链接请求
var url="ws://" + location.host + "/ws"; //是open, on_message, on_close所在类映射的路由。是通过ws协议,而不是http
var ws= new WebSocket(url);//在浏览器打开一个socket 服务器打开一个socket ws.onopen=function(){
$('#status').text('已经建立链接');
var tishi = $('.tishi');
var name = tishi.attr('username');
tishi.append("<div>"+name+"加入了聊天室...</div>")
}; ws.onclose=function () {
$('#status').text('已经断开链接')
}; //当收到服务器向浏览器推送消息时调用这个函数
ws.onmessage=function(event){ message = JSON.parse(event.data);
if(message.content_html){
append(message);
}else{
append_m(message);
}
}; //点出头像函数
$('.t_gif').click(function(){
$('.t_box').toggle(300);
}); // 点击表情时把点击的表情添加到文本框中
$('#q_ul li').click(function(){
var img = $(this).find("img").clone();
$(".t_input").append(img);
$(".t_input").focus();
}); // 点击发布按钮时调用wsbsocket.send()函数向服务器发送数据
$(".t_btn").click(function(){
var content_html = $('.t_input').html();
console.log(content_html);
var massage = {
"content_html":content_html
};
ws.send(JSON.stringify(massage)); }); // 动态添加发布消息的函数
function append(msg){
//向留言中添加消息
$(".t_all").prepend(function(n){
var content_html='';
var useravatar='';
var datetime1='';
if(msg){
content_html = msg.content_html;
var useravatar = 'defaut_avatar.jpeg';
datetime1 = msg.datetime;
}
return "<div class='t_list animated bounceIn'>"+
"<div class='t_header'>"+
"<img src='/static/images/useravatars/" + useravatar +"' alt='' width='64' height='64' />"+
"</div>"+
"<div class='t_icon'></div>"+
"<div class='t_msg'>"+"<p style='font-size:8px;'>"+
"<a class='name' href='#'>" +msg.name+ " </a>"+
datetime1+"</p>"+content_html+"</div>"+
"<div class='clear'></div>"+
"</div>"
});
$('.t_box').hide(400);
$('.t_input').text('');
$('.t_input').focus();
} // 发布系统消息的函数
function append_m(msg){
$(".system_all").html('');
var target = "";
if(msg.target == "system"){
target = "全体人员"
}else{
target = msg.target
}
var messages = "消息内容:"+msg.content+
" 消息类型:"+
msg.send_type+" 发送者:"+
msg.sender +" 接收者:"+
target+" 时间:"+
msg.datetime;
$(".system_all").html(messages);
}
})
</script>
参考中文文档:https://tornado-zh.readthedocs.io/zh/latest/websocket
tornado-websocket的更多相关文章
- python tornado websocket 实时日志展示
一.主题:实时展示服务器端动态生成的日志文件 二.流程: 1. 客户端浏览器与服务器建立websocket 链接,服务器挂起保存链接实例,等待新内容触发返回动作 2. 日志服务器脚本循环去发现新内容, ...
- python tornado websocket 多聊天室(返回消息给部分连接者)
python tornado 构建多个聊天室, 多个聊天室之间相互独立, 实现服务器端将消息返回给相应的部分客户端! chatHome.py // 服务器端, 渲染主页 --> 聊天室建立web ...
- Tornado websocket应用
应用场景 WebSocket 的特点如下 适合服务器主动推送的场景(好友上线,即时聊天信息,火灾警告,股票涨停等) 相对于Ajax和Long poll等轮询技术,它更高效,不耗费网络带宽和计算资源 它 ...
- [tornado]websocket 最简单demo
想法 前两天想看看django 长轮询或者是websocket的方案,发现都不太好使. tornado很适合做这个工作,于是找了些资料,参照了做了个最简单demo,以便备用. 具体的概念就不说了,to ...
- tornado websocket聊天室
1.app.py #!/usr/bin/env python # -*- coding:utf-8 -*- import uuid import json import tornado.ioloop ...
- tornado WebSocket详解
1.什么是WebSocketwebsocket和长轮询的区别是客户端和服务器之间是持久连接的双向通信.协议使用ws://URL格式,但它在是在标准HTTP上实现的. 2.tornado的WebSock ...
- nginx,tornado,websocket,supervisord配置成型
因为要上生产环境,所以配置还是专业一些比较好. nginx.conf upstream websocket_host { server 127.0.0.1:9527; } location /ws_l ...
- Tornado WebSocket简单聊天
Tornado实现了对socket的封装:tornado.web.RequestHandler 工程目录: 1.主程序 manage.py import tornado.web import torn ...
- tornado+websocket+mongodb实现在线视屏文字聊天
最近学了tornado和mongo,所以结合websocket 实现一个聊天功能,从而加深一下相关知识点的印象 1.websocket概览 webscoket是一种全双工通信模式的协议,客户端连接服务 ...
- websocket 与 tornado 的结合
对于socket是不陌生的,但是对于websocket我却是陌生的,不同于https,在网页中使用websocket可以同样起到ajax的作用,默默发送数据... 在script中: ws = new ...
随机推荐
- Linux 命令自动补齐快捷键
Linux 命令自动补齐快捷键 : TAB
- newifi mini将led指示灯引出当gpio使用
之前买了个newifi mini的路由器,CPU是mt7620a的,有7个led指示灯.现在想要把控制led灯的gpio引出来,方便其他驱动或应用的开发. 一.硬件部分 1.联想路由 现在想要把USB ...
- PICT测试工具的安装及使用
PICT工具就是在微软公司出品一款成对组合的命令行生成工具,现在已经对外提供,可以在互联网上下载到 .PICT 可以有效地按照两两测试的原理,进行测试用例设计.在使用PICT时,需要输入与测试用例相关 ...
- sofa-rpc 服务端源码流程走读
sofa-rpc是阿里开源的一款高性能的rpc框架,这篇文章主要是对sofa-rpc provider启动服务流程的一个代码走读,下面是我简单绘制的一个基本的关系流程图 下面我们根据sofa-rpc代 ...
- 代码编辑器之notepad++
引用及下载地址:http://www.iplaysoft.com/notepad-plus.html NotePad++ 优秀的支持语法高亮的开源免费编辑器绿色版下载 EditPlus,它始终是一款收 ...
- RTTI D7
RTTI需要引用单元TypeInfo 至于RTTI的数据结构,大家可以参考TypeInfo单元的代码 看例子,先为大家介绍一下根据字符串找到属性,并且对其修改的例子 根据属性字符串找到属性,并修改属性 ...
- VUE简单组件通信
[x] 1.prop组件通信 1.简单理解 2.多层嵌套 [x] 2.使用ref进行组件通信 [x] 3.$emit组件通信 1.prop组件通信 1.简单理解 有点类似于应式的感觉,我不管你要不要只 ...
- Azure SQL 数据库仓库Data Warehouse (1) 入门
<Windows Azure Platform 系列文章目录> 在之前的项目中遇到了客户使用SQL数据仓库的场景,在这里记录一下 1.什么是SQL 数据库仓库 (SQL DW) SQL D ...
- js 把字符串保存为txt文件,并下载到本地
代码如下 exportRaw('text.txt','123123123') function fakeClick(obj) { var ev = document.createEvent(" ...
- Qt深入浅出(十五)QTableView
转载:吓人的猿 TableView 表格视图控件QTableView,需要和QStandardItemModel, 配套使用,这套框架是基于MVC设计模式设计的,M(Model)是QStandardI ...