使用Flask-SocketIO完成服務端和客戶端的雙向通訊
阿新 • • 發佈:2021-07-09
介紹:flask-socketio模組實際上是封裝了flask對websocket的支援,websocket在連線建立階段是通過HTTP的握手方式進行的,這可以看做是為了相容瀏覽器或者使用一些現成的功能來實現,這樣一種捷徑。當連線建立之後,客戶端和服務端之間就不再進行HTTP通訊了,所有資訊互動都由websocket接管。Flask-SocketIO使Flask應用程式可以訪問客戶端和伺服器之間的低延遲雙向通訊,使客戶端建立與伺服器的永久連線。
適用的場景:後臺產生新的資料,需要在前臺頁面馬上展示出來,例如資料監控、統計圖實時變化更新等。
當然,我們可以使用ajax來完成,通過ajax使得前臺定時去後臺索要資料,但如果訊息頻繁,ajax需要不斷的建立和釋放連線,效果明顯不如後端直接推送資料到前臺更加合適。
Flask-SocketIO的使用
pip install flask-socketio
一個簡單使用SocketIO的完整例項
功能:後臺五秒隨機產生十個數字,在前臺模版中動態重新整理顯示
後臺程式碼:
#encoding:utf-8 #!/usr/bin/env python from flask import Flask, render_template from flask_socketio import SocketIO import random async_mode = None app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' socketio = SocketIO(app) @app.route('/') def index(): return render_template('test.html') @socketio.on('connect', namespace='/test_conn') def test_connect(): while True: socketio.sleep(5) t = random_int_list(1, 100, 10) socketio.emit('server_response', {'data': t}, namespace='/test_conn') def random_int_list(start, stop, length): start, stop = (int(start), int(stop)) if start <= stop else (int(stop), int(start)) length = int(abs(length)) if length else 0 random_list = [] for i in range(length): random_list.append(random.randint(start, stop)) return random_list if __name__ == '__main__': socketio.run(app, debug=True)
頁面模版:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>系統監控走勢圖</title> <script type="text/javascript" src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script> <script type="text/javascript" src="https://cdn.bootcss.com/socket.io/1.5.1/socket.io.min.js"></script> <!-- ECharts 3 引入 --> <script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js"></script> </head> <body> <div id="main" style="height:500px;border:1px solid #ccc;padding:10px;"></div> <script type="text/javascript"> var myChart = echarts.init(document.getElementById('main')); //var myChart = echarts.init($("#main")); myChart.setOption({ title: { text: '系統監控走勢圖' }, tooltip: {}, legend: { data:['cpu'] }, xAxis: { data: [] }, yAxis: {}, series: [{ name: 'cpu', type: 'line', data: [] }] }); var time = ["","","","","","","","","",""], cpu = [0,0,0,0,0,0,0,0,0,0] //準備好統一的 callback 函式 var update_mychart = function (res) { //res是json格式的response物件 // 隱藏載入動畫 myChart.hideLoading(); // 準備資料 time.push(res.data[0]); cpu.push(parseFloat(res.data[1])); if (time.length >= 10){ time.shift(); cpu.shift(); } // 填入資料 myChart.setOption({ xAxis: { data: time }, series: [{ name: 'cpu', // 根據名字對應到相應的系列 data: cpu }] }); }; // 首次顯示載入動畫 myChart.showLoading(); // 建立socket連線,等待伺服器“推送”資料,用回撥函式更新圖表 $(document).ready(function() { namespace = '/test'; var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace); console.log("1111",socket); console.log(location.protocol + '//' + document.domain + ':' + location.port + namespace); socket.on('server_response', function(res) { update_mychart(res); console.log("ret_data",res) }); }); </script> </body> </html>
目錄結構: