• 服务端主动给客户端推送消息


    在了解这个之前,先要知道ajax,队列和递归

    ajax操作

    异步提交,局部刷新。用它就可以实现轮询/长轮询

    创建django项目

    views

    from django.shortcuts import render,HttpResponse
    import json
    from django.http import JsonResponse
    # Create your views here.
    
    # 验证ajax
    def ab_dy(request):
        if request.method == 'post':
           back_dic = {'username':'tony'}
           # return HttpResponse(json.dumps(back_dic))  # 需要dataType参数
           return JsonResponse((back_dic))  # 不需要dataType参数
        return render(request,'ab_dy.html')

    templates

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>ajax验证</title>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <script src="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
    </head>
    
    
    <body>
    <button id="d1">提交</button>
    
    <script>
        $('#d1').click(function () {
                $.ajax({
            url:'',   # 后端服务地址
            type:'post',  # 请求方式
            data:{},  # 发送的数据
            {#dataType:'JSON',#}   # 如果django后端是通过HttpResponse返回数据的那么不会自动返序列化,而如果是JsonResponse则会自动转化,该参数可以不指定
            success:function (args) {
                alert(typeof args)  # 执行成功之后需要进行的操作  异步回调
    
            }
        })
    
        })
    
    </script>
    </body>
    </html>

    队列

    队列:先进先出

    堆栈:先进后出

    import queue
    
    
    q = queue.Queue()  # 创建一个队列
    
    
    q.put('jason')  # 朝队列中丢数据
    q.put('egon')
    
    
    v1 = q.get()  # 获取数据
    v2 = q.get()
    # v3 = q.get()  # 如果没有数据了,get方法默认会一直阻塞
    try:
        v3 = q.get(timeout=3)  # 等3秒 之后还没数据直接报错   queue.Empty
    except queue.Empty as e:
        print(e)
    print(v1,v2)
    # 注意该队列并不会用于实际生产 主要是用来做本地的测试
    # 实际生产建议使用redis、kafka、rebittMQ

    递归

    # python最大递归深度多少呀 997、998、... 官网说是1000
    def func():
          func()
    func()
    
    # 在js中 根本没有递归的概念 函数内部自己调用自己是可以的 属于正常事件范畴
    function func1(){
      $.ajax({
        url:'',
        type:'get',
        data:{},
        success:function(args){
          func1()
        }
      }) 
    }
    $(function(){  # 等待页面加载完毕之后执行函数内的代码
         func1()
    })

    轮询

    效率低、基本不用

    让浏览器定时朝后端发送请求(通过ajax向后端偷偷发送数据),比如每隔五秒钟发一次请求,那么你的数据延迟就可能会高达五秒
    
    不足之处:
    数据延迟
    消耗资源过大
    请求次数太多

    长轮询

    兼容性好

    # 队列+ajax
    服务端给每个客户端建立队列,让浏览器通过ajax朝服务端要数据,去各自的队列中获取
    如果没有数据则会阻塞但是不会一直阻塞,比如阻塞你30秒,还没有数据则返回,然后让客户端浏览器再次发送请求数据的请求
    
    相对于轮询
        基本是没有消息延迟的
        请求次数降低了很多
      
    # web版本的qq和微信基本上用的都是这么一个逻辑

    基于ajax及队列实现长轮询的功能

    1.首页自定义用户唯一表示,给每个用户初始化一个队列
    2.发送按钮绑定点击事件 后端讲数据放入每一个队列中
    3.书写自动获取数据的ajax代码 循环调用
    4.前端获取数据DOM操作渲染页面

    views

    #全局大字典
    q_dict = {}  # {'唯一标识':队列...}
    
    def ab_b1(request):
        # 获取自定义的客户端唯一标识
        name = request.request.GET.get('name')
        # 给每一个客户端创建一个队列
        q_dict[name] = queue.Queue()
        return render(request,'ab_b1.html',locals())
    
    def send_msg(request):
        if request.method == 'post':
            # 获取用户发送的消息
            content = request.POST.get('content')
            # 将该消息传递给所有的队列
            for q in q_dict.values():
                q.put(content)
            return HttpResponse('ok')
    
    def get_msg(request):
        name = request.GET.get('name')
        # 拿到对应的队列
        q = q_dict.get(name)
        #将队列中可能又取出并返回给前端浏览器得数据
    
        # 定义一个字典与ajax进行交互
        back_dic   = {'status':True,'msg':''}
        try:
            data = q.get(timeout=10)  # 等10s 没有则直接报错
            back_dic['msg'] = data
        except queue.Empty as e:
            back_dic['status'] = False
        return JsonResponse(back_dic)

    templates

    $('#d1').click(function () {
            $.ajax({
                url:'/send_msg/',
                type:'post',
                data:{'content':$('#d2').val()},
                dataType:'JSON',
                success:function (args) {
                }
            })
        });
        function getMsg(){
            $.ajax({
                url:'/get_msg/',
                type:'get',
                data:{'name':'{{ name }}'},  // 只要当前登陆人的队列中的数据
                {#dataType:'JSON',#}
                success:function (args) {
                    // 针对返回的消息做相应的处理
                    if(args.status){
                        // 有消息则渲染页面  讲消息全局放到聊天纪录里面
                        // 1 创建标签
                        var pEle = $('<p>');
                        // 2 给标签设置文本内容
                        pEle.text(args.msg);
                        // 3 讲创建好的标签添加到聊天记录div标签内
                        $('#content').append(pEle)
                    }else{
                        // 没有消息 则继续发送
                    }
                    getMsg()  // 循环请求数据
                }
            })
        }
        $(function () {
            getMsg()  // 等待页面加载完毕自动执行
        })

    websocket

    真正的做到服务端发送消息而不再是被动的发送

    """
    HTTP协议  网络协议(不加密传输)
    HTTPS协议 网络协议(加密传输)
        上面两个协议都是短链接
    
    websocket网络协议  (加密传输)
        浏览器和服务端创建链接之后 默认不再断开 
        两端都可以基于该链接收发消息
        websocket的诞生能够真正做到服务端发送消息而不再是被动的发送
    """

    websocket内部原理

    """
    分成两大部分
        1.握手环节:验证服务端是否支持websocket协议
            先连接服务器
            
            浏览器产生一个随机字符串 给服务端发送一份(请求头) 自己留一份
            Sec-WebSocket-Key: ePW8kp1XqLNWbJxE/Q38SA==
            服务端和客户端都对随机字符串做下面的操作
            
            随机字符串 + magic string拼接
            然后再讲拼接好的结果进行加密处理(sha1/base64)的到密文
            
            浏览器自动比对双方产生的密文是否一致,如果一致说明服务端支持websocket
            如果不一致会报错
            
            假设比对上了 建立websocket链接 基于该链接收发消息
            
        2.收发数据
            密文传输 >>> 必然要涉及解密(全球统一)的过程
            基于网络传输的数据都是二进制格式 对应到我们python中就是bytes类型
            
            数据解密过程
                1.先读取数据的第二个字节的后7位(payload) 
                根据7位数据的大小来指定不同的解密流程
                    =127:再往后读取8个字节
                    =126:再往后读取2个字节
                    <=125:不再往后读取
                    
                除去前面读取的数据之外 再往后读4个字节(masking-key)
                拿着它去解析后面的真实数据(依据一个计算公式)
    """

  • 相关阅读:
    calc常用
    windbg学习---.browse打开一个新的command 窗口
    Native wifi API使用
    驱动学习---PAE--virtual address to physics address
    windbg学习.formats--转换成各种进制
    windbg学习---!thread和.thread
    windbg学习----.process
    windbg学习---!process
    windbg命令----!idt
    16进制转换成字符串
  • 原文地址:https://www.cnblogs.com/xiongying4/p/12323694.html
Copyright © 2020-2023  润新知