ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python websocket Django 实时消息推送

2021-05-12 18:07:48  阅读:248  来源: 互联网

标签:username function websocket python Django ws data 连接


   WebSocket 是什么?

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

 

1. django-websocket 是旧版本的,现在已经没有人维护了。dwebsocket是新版的,推荐使用dwebsocket;

安装dwebsocket

 python setup.py install

整个demo:

1.项目结构:

2.HelloWorld项目代码:

urls.py代码:

from django.conf.urls import url
from django.contrib import admin
import views


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/(?P<username>\w+)', views.gotoIndex),
    url(r'websocketLink/(?P<username>\w+)', views.websocketLink)# webSocket 链接
]

views.py

# coding=utf8
from django.shortcuts import render
import threading
from models import Ad
from dwebsocket.decorators import accept_websocket
import json
# from model_admin.models import MessageLog
# 跳转到主页

def gotoIndex(request, username):
    return render(request, 'index.html', {'username': username})



# 存储连接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))

            # 监听接收客户端发送的消息 或者 客户端断开连接
                       sql = ("select id,code,name "
                   "from "
                   "prov_ad  order by create_date desc limit 1"
                   )

            data_list = Ad.objects.raw(sql)
            datas = []
            for item in data_list:
                datas.append({
                    'id': item.id,
                    'name': item.name,  # 区域名称
                    'code': item.code,  # 区域编码
                    'long': item.long,  # 经度
                    'lat': item.lat  # 纬度
                })
            send(username,datas)
        except Exception as e:
            print e
        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], { 'data': data})
except BaseException:
        pass
finally:
        pass

index.html代码:

<!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">
     var websocket;
     var userId=$("#userId").val();
    var name= '{{username}}';
var lockReconnect = false;  //避免ws重复连接
var ws = null;          // 判断当前浏览器是否支持WebSocket
var wsUrl = "ws://localhost:9000/websocketLink/"+name;
createWebSocket(wsUrl);   //连接ws

function createWebSocket(url) {
    try{
        if('WebSocket' in window){
            ws = new WebSocket(url);
        }else if('MozWebSocket' in window){
            ws = new MozWebSocket(url);
        }else{
              alert("您的浏览器不支持websocket协议,建议使用新版谷歌、火狐等浏览器,请勿使用IE10以下浏览器,360浏览器请使用极速模式,不要使用兼容模式!");
        }
        initEventHandle();
    }catch(e){
        reconnect(url);
        console.log(e);
    }
}
  
function initEventHandle() {

    ws.onclose = function () {
        reconnect(wsUrl);
        console.log("llws连接关闭!" + new Date().toUTCString());
    };
    ws.onerror = function () {
        reconnect(wsUrl);
        console.log("llws连接错误!");
    };
    ws.onopen = function () {
        console.log("llws连接成功!" + new Date().toUTCString());
        heartCheck.reset().start();      //心跳检测重置
    };
    ws.onmessage = function (event) {    //如果获取到消息,心跳检测重置
        console.log("llws收到消息啦:" + event.data);
        if (event.data != 'pong') {
            var obj = eval("(" + event.data + ")");
            var data =JSON.parse(event.data)
        }
         heartCheck.reset().start();      //心跳检测重置
    }
}
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
    ws.close();
}

function reconnect(url) {
    if(lockReconnect) return;
    lockReconnect = true;
    setTimeout(function () {     //没连接上会一直重连,设置延迟避免请求过多
        createWebSocket(url);
        lockReconnect = false;
    }, 544000);
}

//心跳检测
var heartCheck = {
    timeout: 5403000,        //9分钟发一次心跳
    timeoutObj: null,
    serverTimeoutObj: null,
    reset: function(){
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
        return this;
    },
    start: function(){
        var self = this;
        this.timeoutObj = setTimeout(function(){
            //这里发送一个心跳,后端收到后,返回一个心跳消息,
            //onmessage拿到返回的心跳就说明连接正常
            ws.send("ping");
            console.log("ping!")
            self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
                ws.close();     //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
            }, self.timeout)
        }, this.timeout)
    }
}
 </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>

 

Nginx部署dwebsocket服务

 

如果项目部署到nginx服务上,你的项目要用到dwebsocket服务

我使用的是nginx+uwsgi

一.首要需要启一个主服务:

配置nginx.conf、uwsgi.ini,正常启动服务就可以了。

二.还需要启动websocket服务,才能让ws://服务器ip进行通信

1.在项目对应的settings.py里添加下面配置,不然会提示报错:handshake的返回400,也就是客户端不合法

WEBSOCKET_FACTORY_CLASS="dwebsocket.backends.uwsgi.factory.uWsgiWebSocketFactory"

2.在新的uwsgi.ini文件里添加下面配置:
DJANGO_SETTINGS_MODULE=项目路径.settings

启动websocket服务

 

3.项目里添加的dwebsocket服务就开启了

正如图中所示:

运行效果入下:

 

标签:username,function,websocket,python,Django,ws,data,连接
来源: https://blog.51cto.com/u_12768449/2771640

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有