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 ...
随机推荐
- hadoop不同版本有哪些
一.Hadoop是什么? 首次听到hadoop这次单词,相信很多人跟我当时是一样,不免心中画上一个大大的问号——这是什么东西?Hadoop是什么?百度百科的解释是:Hadoop是一个由Apache基金 ...
- C#:匿名类型
匿名类型和var关键字是Visual C# 3.0提供的一个新特性,var是隐式类型而并不是类型javascript中的var. var user = new { Id = 1, Name = &qu ...
- Vim插件集合
插件Nerdtree实现浏览文件系统并打开文件或目录,在window中是非常不错的插件,但是在Ubuntu中这个插件就是一坑,特别提示,且无解.若在Ubuntu中使用目录浏览插件,建议使用其他插件,如 ...
- Combobox中禁止鼠标中键滚动list列表
//第1种方法 procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; Mo ...
- 黄聪:保持web页面生成的app一直处于用户登录状态不退出
用户登录了会员中心,怎么保持登录状态! 由于封壳的内核及组件肯定没有浏览器APP应用那么强大,所以目前暂时的解决方案是: jquery.cookie.js 本文转载至:https://www.cnb ...
- 黄聪:C#“多线程线程间操作无效: 从不是创建控件的线程访问它。”,跨线程修改控件属性解决方案
解决方案就是使用代理,在代理中调用主线程的方法来控制控件 /// <summary> /// 声明代理 /// </summary> delegate void SetText ...
- Lucene 4.0 正式版发布,亮点特性中文解读[转]
http://blog.csdn.net/accesine960/article/details/8066877 2012年10月12日,Lucene 4.0正式发布了(点击这里下载最新版),这个版本 ...
- java翻转字符串中的单词
效果: 输入: "java and python" 输出: "avaj dna nohtyp" 代码: 版本1: 不考虑字符串开头有空格,单词间有多个空格空格的 ...
- firefox驱动的下载地址
https://www.seleniumhq.org/download/
- Python——ipython(python programming)
Tab自动补充 Ctrl+c中断程序 ?帮助调出文档 _得到上次的结果 ,__的到上上次结果,___得到上上次结果 %开头的为魔术命令 %timeit 得到运算时间,多次求平均 %%time ...