Flask 網路套接字

Salman Mehmood 2022年7月18日
Flask 網路套接字

通過這個解釋,我們將瞭解 WebSocket 是什麼以及它是如何在客戶端和伺服器之間工作的。我們還將學習如何藉助 Flask 中的 flask_socketio 模組製作一個實時聊天應用程式。

藉助 Flask 中的 flask_socketio WebSocket 建立實時應用程式

WebSocket 是一種在客戶端和伺服器之間開啟套接字的方法。使用 WebSockets,我們可以實時傳送訊息。

它不是典型的網路請求-響應模型;就像一個開放的連線永遠存在,伺服器和客戶端可以不斷地相互對話。

現在讓我們構建聊天應用程式;我們將處理的第一方面是伺服器端。有兩個方面:第一個是伺服器端,它將由 Flask 處理,第二個是客戶端,它將由 JavaScript 處理。

擴充套件 flask_socketio 允許客戶端與伺服器連線,因此我們需要使用以下命令安裝 flask_socketio 模組。

pip install Flask-SocketIO

它將安裝 flask_socketio 以及它需要的任何依賴項。flask_socketio 與典型的 Flask 應用程式非常相似,模式相同,但我們使用的一些東西略有不同。

我們將匯入一些類和 send 函式來構建這個應用程式。然後我們將建立一個應用程式例項,由於所有訊息都是加密的,我們需要金鑰;我們將金鑰定義為 config 值。

現在我們將為 SocketIO() 類建立一個物件並通過傳遞應用程式來例項化它,第二個引數是允許所有域。

app.config['SECRET_KEY'] = 'ffff111jjj52'
socketio = SocketIO(app, cors_allowed_origins='*')

現在我們將定義一個路由來監聽我們在路由中指定的特定事件,然後我們將建立一個函式,當我們傳送函式名稱為 Text_MSG() 的訊息時將呼叫該函式。

這個函式接受一個名為 msg 的引數,我們將把它列印出來以確保控制檯上的一切正常。

我們將接收來自任何人的訊息,並將其傳送給當時連線到伺服器的每個人。我們將使用 send() 函式,該函式將採用兩個引數:一個是 msg,它是一條文字訊息,第二個是一個 broadcast,它等於 True

如果我們將 False 傳遞給 broadcast 或不傳遞此引數,那麼它將預設將訊息傳送給我們首先從那裡獲得訊息的任何人。

由於我們正在廣播併傳送我們從一個客戶端收到的相同訊息,因此我們會將其傳送回所有客戶端,包括我們剛剛收到它的客戶端。

@socketio.on('message')
def Text_MSG(msg):
    print('text-message: ' + msg)
    send(msg, broadcast=True)

我們將不使用 app.run(),而是使用 socketio.run(app),它具有在實時環境中執行 Flask 應用程式的額外功能。

if __name__ == '__main__':
    socketio.run(app)

讓我們進入前端的建築物,它將是一個 HTML 頁面。我們將從 CDN 為客戶端 socket.io 庫匯入幾個指令碼。我們還將使用 jQuery 來處理按鈕上的單擊事件。

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.8/socket.io.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

body 標籤中,我們將編寫 JavaScript 程式碼。因為我們使用的是 jQuery,所以我們必須使用 ready() 方法,並且在這個 $(document).ready() 中,我們需要連線到執行 Flask 應用程式的伺服器。

我們將建立一個名為 socket 的物件並使用 connect() 對其進行例項化,並將 URL 傳遞給 Flask 伺服器。一旦我們建立了一個物件,我們需要確保當我們連線到伺服器時,我們可以向它傳送訊息。

$(document).ready(function() {

    var socket = io.connect('http://127.0.0.1:5000');

    socket.on('connect', function() {
        socket.send('User has connected!');
    });

});

這意味著我們正在監聽一個特定的事件,並且每當我們第一次連線到伺服器時都會發生連線事件,一旦發生,它就會呼叫這個 socket.on() 回撥函式。這個回撥函式會傳送給使用者已經連線的伺服器,伺服器將讀取它併傳送給每個人。

讓我們新增程式碼來映象傳送到伺服器的任何訊息,以便我們將偵聽另一個事件而不是 connectmessage 回撥函式會將訊息附加到我們的訊息列表中,我們還將使用訊息文字固定一個列表項。

socket.on('message', function(msg) {
    $("#messages").append('<li>'+msg+'</li>');
    console.log('Received message');
});

我們要做的最後一件事是允許使用按鈕傳送訊息。因此,我們將在傳送按鈕上放置一個點選事件,並將 myMessage id 與 input 標籤 id 附加在一起。

一旦我們傳送它,我們將使用 val('') 方法清除我們的訊息以便為新訊息騰出空間。

$('#sendbutton').on('click', function() {
    socket.send($('#myMessage').val());
    $('#myMessage').val('');
});

現在我們將儲存它並執行 Flask 伺服器,然後我們將在兩個視窗中開啟一個 index.html 檔案。當我們在輸入欄位中輸入一些文字並點選傳送按鈕時,我們將同時在另一個視窗中接收訊息。

Flask WebSockets 輸出

注意:如果出現錯誤,請在終端中執行以下命令。

pip install --upgrade python-socketio==4.6.0

pip install --upgrade python-engineio==3.13.2

pip install --upgrade Flask-SocketIO==4.3.1

完整的 Python 程式碼:

from flask import Flask
from flask_socketio import SocketIO, send

app = Flask(__name__)
app.config['SECRET_KEY'] = 'ffff111jjj52'
socketio = SocketIO(app, cors_allowed_origins='*')

@socketio.on('message')
def Text_MSG(msg):
    print('text-message: ' + msg)
    send(msg, broadcast=True)


if __name__ == '__main__':
    socketio.run(app)

完整的 HTML 程式碼:

<html>
<head>
<title>Chat Room</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.8/socket.io.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {

    var socket = io.connect('http://127.0.0.1:5000');

    socket.on('connect', function() {
        socket.send('User has connected!');
    });

    socket.on('message', function(msg) {
        $("#messages").append('<li>'+msg+'</li>');
        console.log('Received message');
    });

    $('#sendbutton').on('click', function() {
        socket.send($('#myMessage').val());
        $('#myMessage').val('');
    });

});
</script>
<ul id="messages"></ul>
<input type="text" id="myMessage">
<button id="sendbutton">Send</button>
</body>
</html>
Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn