python websocket Django 实时消息推送

概述:

   WebSocket 是什么?

     WebSocket 是 HTML5 提供的一种浏览器与服务器间进行全双工通讯的协议。依靠这种协议可以实现客户端和服务器端 ,一次握手,双向实时通信。

WebSocket 客户端:

<!DOCTYPE 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.name

    class Meta:
        verbose_name = "消息记录"
        verbose_name_plural = "消息记录"
        db_table = "m_message_log"

测试页面   222 用户名

http://127.0.0.1:8000/index/222

效果展示  (消息提示 样式demo里面有)

demo 下载

https://download.csdn.net/download/xianailili/10633792

猜你喜欢

转载自blog.csdn.net/xianailili/article/details/82180114