1. 程式人生 > >輪詢 長輪詢 websocket

輪詢 長輪詢 websocket

輪詢

  特點:每隔一段時間不短向後端傳送請求

  缺點:消耗大,延遲

from flask import Flask,render_template,request,jsonify

app = Flask(__name__)

USERS = {
    1:{"name":"Alex","count":250},
    2:{"name":"yuanhao","count":250},
    3:{"name":"bossjin","count":250},

}

@app.route("/")
def index():
    return render_template("
index.html",user=USERS) @app.route("/vote",methods=["POST"]) def vote(): uid = request.json.get("uid") USERS[uid]["count"] += 1 return "投票成功" @app.route("/get_vote") def get_vote(): # 返回所有的users資料 return jsonify(USERS) if __name__ == '__main__': app.run()
<!DOCTYPE html
> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>投票系統</h1> <ul> {% for (key,value) in users.items() %} <li id="{{key}}" onclick="vote({{key}})">{{value.name}}:({{value.count}})</
li> {% endfor %} </ul> <script> function vote(uid) { //向後端傳送投票請求 帶user_id axios.request({ url:"/vote", method:"POST", data:{ uid:uid } }).then(function (res) { console.log(res) }) } function get_vote() { axios.request({ url:"/get_vote", method:"GET" }).then(function (res) { console.log(res); //向後端發獲取實時資料的請求 //拿到資料之後更新頁面 users = res.data; for(let uid in users){ //根據key獲取li標籤,改變innnerText let liEle = document.getElementById(uid) liEle.innerText = `${users[uid]["name"]}:(${users[uid]["count"]})` } }) } window.onload = function () { setInterval(get_vote(),2) } </script> </body> </html>

 

長輪詢

  特點:滿足實時更新

  缺點:消耗也大,但是請求次數比輪詢小

  實現:

    利用queue物件實現請求阻塞

    每個請求進來都要生成一個q物件

    如果有人投票給所有的q物件put資料

    拿資料請求從自己的q物件get資料

from flask import Flask,request,render_template,session,jsonify
import queue
import uuid


app = Flask(__name__)
app.secret_key = "xxx"

USERS = {
    1:{"name":"alex","count":25},
    2:{"name":"yuanhao","count":25},
    3:{"name":"bossjin","count":25},

}

Q_DICT = {}


@app.route("/")
def index():
    user_uuid = str(uuid.uuid4())
    session["user_uuid"] = user_uuid
    Q_DICT[user_uuid] = queue.Queue()
    return render_template("index3.html",users=USERS)


@app.route("/vote",methods=["POST"])
def vote():
    # 投票
    uid = request.json.get("uid")
    USERS[uid]["count"] += 1
    for q in Q_DICT.values():
        q.put(USERS)
    return "投票成功"


@app.route("/get_vote")
def get_vote():
    user_uuid = session.get("user_uuid","")
    q = Q_DICT[user_uuid]
    try:
        ret = q.get(timeout=30)
    except queue.Empty:
        ret = ""
    return jsonify(ret)



if __name__ == '__main__':
    app.run()
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.js"></script>
</head>
<body>
<h1>投票系統</h1>
<ul>
    {% for(key,val) in users.items() %}
    <li id="{{key}}" onclick=vote({{key}})>{{val.name}}:({{val.count}})</li>
    {% endfor %}
</ul>
<script>
    function vote(uid) {
        axios.request({
            url:"/vote",
            method:"POST",
            data:{
                uid:uid,
            }
        }).then(function (res) {
            console.log(res)
        })
    }
    function get_vote() {
        axios.request({
            url:"get_vote",
            method:"GET",
        }).then(function (res) {
            if (res.data != "") {
                let users = res.data;
                for(let uid in users){
                    liELe = document.getElementById(uid);
                    liELe.innerText = `${users[uid]["name"]}:(${users[uid]["count"]})`
                }
            }
            get_vote()
        })

    }
    window.onload = function () {
        get_vote()
    }
</script>
</body>
</html>

 

websocket

  HTTP協議:短連結,無狀態,基於TCP/UDP協議進行傳輸資料

  TCP/UDP:傳輸協議

  socket:套接字,API介面

  websocket:H5出的新協議,解決輪詢的效能問題

  特點:

    1.握手,基於HTTP進行握手

    2.傳送資料加密

    3.保持連線不斷開

      下載安裝

pip install gevent-websocket # Flask沒有websocket

  建立一個支援websocket協議連線

from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
# 拿到websocket物件
ws = request.environ.get("wsgi.websocket")
# 傳送資料
ws.send()  # json
# 接收資料
ws.receive()

if __name__ == "__main___"
    http_server = WSGIServer(('0.0.0.0', 5000), app, handler_class=WebSocketHandler)
    http_server.serve_forever()
    # 即支援HTTP 也支援websocket

  前端發起websocket連線

let ws = new WebSocket("ws://0.0.0.0:5000")
# 前端傳送資料
ws.send("xxx")
# 接收資料
ws.onmessage = function(event){
    data = event.data
    # 資料型別的轉換    
}