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