python之輪詢、長輪詢、websocket

輪詢

ajax輪詢 ,ajax輪詢 的原理很是簡單,讓瀏覽器隔個幾秒就發送一次請求,詢問服務器是否有新信息。html

一、後端代碼前端

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()

二、前端代碼html5

<!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給客戶端。直到有消        息才返回或超時,返回完以後,客戶端再次創建鏈接,周而復始,基於事件的觸發,一個事件接一個事件。 jquery

Ajax輪詢與long poll都屬於不斷髮送http請求,而後等待服務器處理,能夠看到http協議一個特色,被動性,服務端不能主動聯繫客戶端,只有客戶端發起。web

缺點:Ajax輪詢須要服務器有很快的處理速度與快速響應。long poll須要很高的併發,體如今同時容納請求的能力。ajax

一、後端代碼json

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)

二、前端代碼flask

<!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對象存儲,可以實現實時推送。瀏覽器

一、安裝

pip3 install gevent-websocket

二、後端代碼

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()

三、前端代碼

#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>
相關文章
相關標籤/搜索