• python之轮询、长轮询、websocket


    轮询

    ajax轮询 ,ajax轮询 的原理非常简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。

    1、后端代码

    from flask import Flask,render_template
    
    app = Flask(__name__)
    
    UUUU = {
        '1':{'name':'','count':1},
        '2':{'name':'','count':1},
        '3':{'name':'','count':1},
    }
    
    
    @app.route('/index')
    def index():
        return render_template('index.html',user_list = UUUU)
    
    if __name__ == '__main__':
        app.run()

    2、前端代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>最帅的</title>
    </head>
    <body>
        <ul>
            {% for k,v in user_list.items() %}
                <li>{{k}}: {{v.name}} {{v.count}} </li>
            {% endfor %}
        </ul>
        <script>
            # 重点2秒重新请求
            function reload() {
                window.location.reload()
            }
            setInterval(reload,2000)
    
        </script>
    </body>
    </html>    

    长轮询

    long poll 其实原理跟 ajax轮询 差不多,都是采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消        息才返回或超时,返回完之后,客户端再次建立连接,周而复始,基于事件的触发,一个事件接一个事件。 

    Ajax轮询与long poll都属于不断发送http请求,然后等待服务器处理,可以看到http协议一个特点,被动性,服务端不能主动联系客户端,只有客户端发起。

    缺点:Ajax轮询需要服务器有很快的处理速度与快速响应。long poll需要很高的并发,体现在同时容纳请求的能力。

    1、后端代码

    from flask import Flask,render_template,request,session,redirect,jsonify
    from uuid import uuid4
    from queue import Queue,Empty
    import json
    app = Flask(__name__)
    app.secret_key = "asdfasdfasdf"
    UUUU = {
        '1':{'name':'','count':1},
        '2':{'name':'','count':1},
        '3':{'name':'','count':1},
    }
    
    # 为每个登录用户保存
    # dfasdfadsfasdfadf: Queue()
    USER_QUEUE_DICT = {
    
    }
    
    @app.before_request
    def check_login():
        if request.path == '/login':
            return None
        user_info = session.get('user_info')
        if not user_info:
            return redirect('/login')
    
    @app.route('/login',methods=['GET','POST'])
    def login():
        if request.method == "GET":
            return render_template('login.html')
        else:
            user = request.form.get('user')
            nid = str(uuid4())
            USER_QUEUE_DICT[nid] = Queue()
            session['user_info'] = {'nid':nid, 'user':user }
            return redirect('/index')
    
    
    @app.route('/index')
    def index():
        return render_template('index.html',user_list = UUUU)
    
    @app.route('/query')
    def query():
        """每个用户查询最新投票信息"""
        ret = {'status':True,'data':None}
        current_user_nid = session['user_info']['nid']
        queue = USER_QUEUE_DICT[current_user_nid]
        try:
            # {'uid':1, 'count':6}
            ret['data'] = queue.get(timeout=10) #十秒后断开,再连
        except Empty as e:
            ret['status'] = False
        # return jsonify(ret)
        return json.dumps(ret)
    
    
    @app.route('/vote')
    def vote():
        """
        用户投票
        :return:
        """
        uid = request.args.get('uid')
        old = UUUU[uid]['count']
        new = old + 1
        UUUU[uid]['count'] = new
    
        for q in USER_QUEUE_DICT.values():
            q.put({'uid':uid, 'count':new})
    
        return "投票成功"
    
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0',threaded=True)

    2、前端代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>最帅</title>
    </head>
    <body>
        <ul>
            {% for k,v in user_list.items() %}
                <li style="cursor: pointer;" ondblclick="doVote('{{k}}')" id="user_{{k}}">{{k}}: {{v.name}} <span>{{v.count}}</span> </li>
            {% endfor %}
        </ul>
        <!--<script src="/static/jquery-1.12.4.js"></script>-->
        <script src="{{ url_for('static',filename='jquery-1.12.4.js') }}"></script>
        <script>
            
            $(function () {
                get_data();
            })
            
            /*
            查询最新信息
             */
            function get_data() {
                $.ajax({
                    url: '/query',
                    type:'GET',
                    dataType:'json',
                    success:function (arg) {
                        if(arg.status){
                            var liId = "#user_" + arg.data.uid;
                            $(liId).find('span').text(arg.data.count);
                        }
                        get_data();
                    }
                    
                })
            }
    
            /*
            投票
             */
            function doVote(uid) {
                $.ajax({
                    url:'/vote', //     /vote?uid=1
                    type:'GET',
                    data:{
                        uid:uid
                    },
                    success:function (arg) {
    
                    }
                })
            }
        </script>
    </body>
    </html>

    websocket

    webSocket是html5一种新的协议,实现了浏览器与服务器之间的全双工通信,能很好的节省服务器资源与带宽,并在服务器端与浏览器端实现实时通行,他建立在TCP之上, 同http一样,通过tcp来传输数据。

       只需要一次HTTP握手,所以说整个通讯过程是建立在一次连接/状态中,服务器端会知道连接的信息,知道客户端关闭请求,同时由服务器主动推送,当有信息需要发送时,直接发送。客户端的连接通过session对象存储,能够实现实时推送。

    1、安装

    pip3 install gevent-websocket

    2、后端代码

    from flask import Flask,render_template,request,session,redirect,jsonify
    import uuid
    from geventwebsocket.handler import WebSocketHandler
    from gevent.pywsgi import WSGIServer
    import json
    
    
    app = Flask(__name__)
    app.secret_key = 'xfsdfqw'
    
    USERS = {
        '1':{'name':'','count':0},
        '2':{'name':'','count':0},
        '3':{'name':'','count':0},
    }
    
    
    @app.before_request
    def before_request():
        if request.path == '/login':
            return None
        user_info = session.get('user_info')
        if user_info:
            return None
        return redirect('/login')
    
    
    @app.route('/login',methods=['GET','POST'])
    def login():
        if request.method == "GET":
            return render_template('login.html')
        else:
            uid = str(uuid.uuid4())
            session['user_info'] = {'id':uid,'name':request.form.get('user')}
            return redirect('/index')
    
    
    @app.route('/index')
    def index():
        return render_template('index.html',users=USERS)
    
    # 为每个登录用户保存socket字典
    WS_DICT = {
    
    }
    
    @app.route('/message')
    def message():
        if request.environ.get('wsgi.websocket'):
            ws = request.environ['wsgi.websocket']
            # 1. 刚连接成功
            uid = session.get('user_info').get('id')
            WS_DICT[uid] = ws
    
            from geventwebsocket.websocket import WebSocket
            while True:
                # 2. 等待用户发送消息,并接受
                message = ws.receive()
                # 关闭:message=None
                if not message:
                    del WS_DICT[uid]
                    break
    
                old = USERS[message]['count']
                new = old + 1
                USERS[message]['count'] = new
    
                data = {'user':message,'count':new}
    
                for k,v in WS_DICT.items():
                    # 3. 向客户端推送消息
                    v.send(json.dumps(data))
    
        return "Connected!"
    
    if __name__ == '__main__':
        http_server = WSGIServer(('127.0.0.1', 5000), app, handler_class=WebSocketHandler)
        http_server.serve_forever()

    3、前端代码

    #login
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form method="post">
        <input type="text" name="user">
        <input type="submit" value="提交">
    </form>
    </body>
    </html>
    # index
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>投票系统</h1>
        <a onclick="closeConn();">关闭连接</a>
        <a onclick="createConn();">创建连接</a>
        <ul>
            {% for k,v in users.items() %}
                <li id="user_{{k}}"  ondblclick="vote('{{k}}')">{{v.name}} <span>{{v.count}}</span> </li>
            {% endfor %}
    
        </ul>
    
        <script src="{{ url_for('static',filename='jquery-3.3.1.min.js')}}"></script>
        <script>
    
            var socket = null;
    
            function socketInit() {
                socket.onopen = function () {
                /* 与服务器端连接成功后,自动执行 */
            };
    
                socket.onmessage = function (event) {
                    /* 服务器端向客户端发送数据时,自动执行 */
                    var response = JSON.parse(event.data); // {'user':1,'count':new}
                    var nid = '#user_' + response.user;
                    $(nid).find('span').text(response.count)
                };
    
                socket.onclose = function (event) {
                    /* 服务器端主动断开连接时,自动执行 */
                };
    
            }
    
            /*
            我要投票
            id:帅哥id
             */
            function vote(id) {
    
                socket.send(id);
            }
    
            function closeConn() {
                socket.close()
            }
            function createConn() {
                socket = new WebSocket("ws://127.0.0.1:5000/message");
                socketInit();
            }
        </script>
    </body>
    </html>
  • 相关阅读:
    安装64位Oracle 10g超详细教程
    Linux同平台Oracle数据库整体物理迁移
    Oracle 删除重复数据只留一条
    linux下通过脚本实现自动重启程序的方法
    Linux查看系统开机时间
    Linux下oracle数据库启动和关闭操作
    curl: (6) Couldn’t resolve host ‘www.ttlsa.com’
    linux 怎么查找oracle11g的安装目录
    Linux系统管理员:不要害怕升级内核
    The Binder Architecture
  • 原文地址:https://www.cnblogs.com/wangshuyang/p/9001604.html
Copyright © 2020-2023  润新知