python websocket Django 实时消息推送
概述:
WebSocket 是什么
WebSocket 是 HTML5 提供的一种浏览器与服务器间进行全双工通讯的协议。依靠这种协议可以实现客户端和服务器端 ,一次握手,双向实时通信.
WebSocket 客户端:
<!DOCKTYPE html> <html> <head> {% load static %} //<link rel="stylesheet" type="text/css" href="{% static 'iziToast/css/iziToast.min.css' %}"> //<script type="text/javascript" src="{% static 'iziToast/js/iziToast.min.js' %}"></script> // <script type="text/javascript" src="{% static 'iziToast/js/websocket.js' %}"></script> <title>django-websocket</title> <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script> <script type="text/javascript">//<![CDATA[ $(function () { var websocket; var name= '{{username}}'; // 首先判断是否 支持 WebSocket name身份标识 我当前用的 用户名, if('WebSocket' in window) { websocket = new WebSocket("ws://localhost:8000/websocketLink/"+name); } else if('MozWebSocket' in window) { websocket = new MozWebSocket("ws://localhost:8000/websocketLink/"+name); } else { websocket = new SockJS("ws://localhost:8000/websocketLink/"+name); } // 打开连接时 formatMsg是我自定义的消息提示 websocket.onopen = function(event) { //formatMsg("系统提示:","您已连接 ,消息提示系统!!",2000) alert("您已连接 ,消息提示系统!!") }; //发送消息 $('#send_message').click(function () { if(!websocket){ alert("Please connect server."); }else{ //websocket.send($('#message').val()); //发送字符串数据类型 websocket.send(JSON.stringify({'title': '通知', 'data': $('#message').val(), 'url': null}));//发送json数据类型 } }); // 收到消息时 websocket.onmessage = function(event) { var data =JSON.parse(event.data); // formatMsg(data.title,data.data,10000) alert(data.data) }; // 错误时 websocket.onerror = function(event) { console.log(" websocket.onerror "); }; // 断开连接时 websocket.onclose = function(event) { //formatMsg("系统提示:","已断开服务器,无法接收消息提示(请重新刷新页面)",2000) alert("已断开服务器,无法接收消息提示(请重新刷新页面)") }; //关闭websocket连接 $('#close_websocket').click(function () { if(websocket){ websocket.close(); } }); }); function formatMsg(title,data,time) { iziToast.show({ color: 'dark', icon: 'icon-contacts', title: title, message: data, timeout: time, position: 'topCenter', transitionIn: 'flipInX', transitionOut: 'flipOutX', progressBarColor: 'rgb(0, 255, 184)', image: 'img/avatar.jpg', imageWidth: 70, layout:2, onClose: function(){ console.info('onClose'); }, iconColor: 'rgb(0, 255, 184)' }); } </script> </head> <body> <br> <input type="text" id="message" value="Hello, World!" /> <button type="button" id="send_message">发送消息</button> <button type="button" id="close_websocket">关闭websocket</button> </body> </html>
WebSocket 服务端:
用的是 dwebsocket
需要手动导入 不是pip安装 工具类 Django 项目不需要 配置 settings.py INSTALLED_APPS
dwebsocket下载地址:
https://download.csdn.net/download/xianailili/10633275
urls.py
# (?P<username>\w+) 设置必传参数 支持中文
url(r'websocketLink/(?P<username>\w+)', websocket.websocketLink# webSocket 链接
views.py
import threading
from dwebsocket.decorators import accept_websocket
# 存储连接websocket的用户
clients = {}
# 记录连接人数 其实没什么卵用 = =
count = 0
# 连接websocket ws://localhost:8000/websocketLink/22
# 因为 websocket 是协议 所以不能用 http或https
@accept_websocket
def websocketLink(request, username):
‘连接websocket’
global count
# 获取连接
if request.is_websocket:
lock = threading.RLock()#rlock线程锁
try:
lock.acquire()#抢占资源
s = {}
# 因为同一个账号打开多个页面连接信息是不同的
if clients.get(username) != None:
# 连接信息 键 连接名 值:连接保存
s[str(request.websocket)] = request.websocket
# 已存在的连接信息继续增加
clients[username].update(s)
else:
# 人数加1
count = count + 1
# 连接信息 键 连接名 值:连接保存
s[str(request.websocket)] = request.websocket
# 新增 用户 连接信息
clients[username] = s
print(“用户人数” + str(count))
# 监听接收客户端发送的消息 或者 客户端断开连接
for message in request.websocket:
if not message:
break
else:
request.websocket.send(message)
finally:
# 通过用户名找到 连接信息 再通过 连接信息 k 找到 v (k就是连接信息)
clients.get(username).pop(str(request.websocket))
#释放锁
lock.release()
# 发送消息
def websocketMsg(client, msg):
import json
# 因为一个账号会有多个页面打开 所以连接信息需要遍历
for cli in client:
‘client客户端 ,msg消息’
b1 = json.dumps(msg).encode(‘utf-8’)
client[cli].send(b1)
# 服务端发送消息
def send(username, title, data, url):
‘username:用户名 title:消息标题 data:消息内容,消息内容:ulr’
try:
if clients[username]:
websocketMsg(clients[username], {‘title’: title, ‘data’: data, ‘url’: url})
# 根据业务需求 可有可无 数据做 持久化
# messageLog = MessageLog(name=username, msg_title=title, msg=data, msg_url=url, is_required=0)
flg = 1
flg = -1
except BaseException:
# messageLog = MessageLog(name=username, msg_title=title, msg=data, msg_url=url, is_required=1)
pass
finally:
pass
# messageLog.save()
models .py
#消息推送
class MessageLog(models.Model):
name = models.CharField(verbose_name=”用户名称”, max_length=100, blank=False, null=False)
msg =models.CharField(verbose_name=”消息”, max_length=100, blank=False, null=False)
msg_title = models.CharField(verbose_name=”消息标题”, max_length=100, blank=False, null=False)
msg_url = models.CharField(verbose_name=”消息url”, max_length=100, blank=False, null=False)
requiredText = ((0, ‘是’), (1, ‘否’))
is_required = models.IntegerField(verbose_name=’是否已读’, choices=requiredText, default=0)
create_time = models.DateTimeField(verbose_name=’创建时间’, auto_now_add=True) # auto_now_add:取新增时候的时间
update_time = models.DateTimeField(verbose_name=’修改时间’, auto_now=True) # 取每次更新的时间
def str(self):
return self.nam
class Meta:
verbose_name = “消息记录”
verbose_name_plural = “消息记录”
db_table = “m_message_log”