1. 程式人生 > 其它 >使用Flask-SocketIO完成服務端和客戶端的雙向通訊

使用Flask-SocketIO完成服務端和客戶端的雙向通訊

介紹: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>

目錄結構: