輪詢 長輪詢 websocket
阿新 • • 發佈:2019-01-05
輪詢
特點:每隔一段時間不短向後端傳送請求
缺點:消耗大,延遲
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 # 資料型別的轉換 }