flask-socketio实现前后端实时通信的功能的示例
作者:今天上上签 发布时间:2021-02-18 22:18:35
一、需求
准备实现一个前后端实时发送消息的功能,即后端发送一条消息,前端就可以接收到该消息并显示在页面上。
二、解决方法
利用Flask-SocketIO实现,Flask-SocketIO使Flask应用程序能够访问客户端和服务器之间的低延迟双向通信。能够很好的解决我们的问题
三、具体实现
步骤一:安装
pip install eventlet
pip install flask-socketio
注意:flask-socketio对版本要求比较严格,如果报错,请更换如下包的版本:
Flask 1.1.4
Flask-SocketIO 4.3.1
python-engineio 3.13.2
python-socketio 4.6.0
步骤二:服务器代码
import time
from flask import Flask, request, render_template
from flask_socketio import SocketIO
from threading import Lock
thread = None
thread_lock = Lock()
app = Flask(__name__)
socketio = SocketIO()
socketio.init_app(app, cors_allowed_origins='*') # 用socketio初始化flask的app
flag1 = 0
flag2 = 0
flag3 = 0
@app.route('/', methods=['POST', 'GET'])
def index():
global flag1
global flag2
global flag3
if request.method == 'POST':
# 模拟执行你的业务逻辑一
time.sleep(5)
# 利用全局变量表明业务逻辑一已完成
flag1 = 1
print("步骤1完成")
# 模拟执行你的业务逻辑二
time.sleep(2)
# 利用全局变量表明业务逻辑二已完成
flag2 = 1
print("步骤2完成")
# 模拟执行你的业务逻辑三
time.sleep(3)
# 利用全局变量表明业务逻辑三已完成
flag3 = 1
print("步骤3完成")
return render_template('t1.html')
@socketio.on('connect', namespace='/test_conn')
def test_connect():
"""
此函数在建立socket连接时被调用
"""
print("socket 建立连接")
global thread
with thread_lock:
print(thread)
if thread is None:
# 如果socket连接,则开启一个线程,专门给前端发送消息
thread = socketio.start_background_task(target=background_thread)
@socketio.on('disconnect', namespace='/test_conn')
def disconnect_msg():
"""
此函数在socket断开时被调用
"""
print('client disconnected!')
def background_thread():
"""
该线程专门用来给前端发送消息
:return:
"""
global flag1
global flag2
global flag3
while True:
if flag1 == 1:
print("进入判断一")
socketio.emit('server_response',
{'data': '步骤一已完成'}, namespace='/test_conn')
flag1 = 2
socketio.sleep(2)
if flag2 == 1 and flag1 == 2:
print("进入判断二")
socketio.emit('server_response',
{'data': '步骤二已完成'}, namespace='/test_conn')
flag2 = 2
socketio.sleep(2)
if flag3 == 1 and flag2 == 2 and flag1 == 2:
print("进入判断三")
socketio.emit('server_response',
{'data': '步骤三已完成'}, namespace='/test_conn')
flag3 = 2
socketio.sleep(2)
if __name__ == '__main__':
socketio.run(app, host='127.0.0.1', port=5000, debug=True)
步骤三:前端代码
前端代码是用vue+element ui编写。(代码中所涉及的js文件可以在百度上自行下载,有很多)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="stylesheet" href="static/css/index.css" rel="external nofollow" > <!-- 引入element的css文件-->
<script src="static/js/vue.js"></script> <!-- 引入vue文件-->
<script src="static/js/index.js"></script> <!-- 引入element的js文件-->
<script src="static/js/axios.min.js"></script> <!--引入axios文件-->
<script type="text/javascript" src="static/js/jquery-1.4.2.min.js"></script> <!--引入jquery文件-->
<script type="text/javascript" src="static/js/socket.io.min.js"></script> <!--引入socket文件-->
</head>
<body>
<div id="test">
<el-button type="primary" size="small" @click="onSubmit()">提交</el-button>
<div id = "t"></div>
</div>
</body>
<script>
// 新建vue环境
new Vue({
el: '#test',
data() {return{} },
methods: {
onSubmit() {
// 向后端发送post请求
axios.post('http://127.0.0.1:5000/');
// 建立socket连接,此时会触发后端的@socketio.on('connect', namespace='/test_conn')路由,执行test_connect函数
let socket = io.connect('http://127.0.0.1:5000/test_conn');
socket.on('server_response', function (res) {
//接收到后端发送过来的消息
var t = res.data;
console.log(t)
if (t) {
// 显示在页面上
$("#t").append(t).append('<br/>');
}
});
}
}
})
</script>
</html>
结果展示
启动flask项目,并访问:
点击提交后,前端发送post请求给后端,并建立socket连接:
同时执行index()函数:
同时前端页面接收到后端发送的消息:
至此,前后端交互功能完成!
四、注意事项
1、我们不能直接在socket连接函数中写一个while循环去发送信息,例如这样:
@socketio.on('connect', namespace='/test_conn')
def test_connect():
while True:
socketio.sleep(5)
t = random.randint(1, 100)
socketio.emit('server_response',
{'data': t},namespace='/test_conn')
虽然这样写,emit函数每次都会执行,理论上客户端应该可以定时收到服务端的随机数。但是结果是客户端根本接收不到,连soketio.on函数都没有触发运行。
原因应该是当服务端陷入死循环,会影响与客户端之间的websocket连接,总之写while true需谨慎。
所以,在flask_socketio的示例程序中,我们 用后台线程 进行while循环以解决这个问题。
2、websocket连接的一个典型应用是实现一个网络聊天室,所以就会有群发和私聊的功能,我们此处演示的示例,是一个群发功能,也就是我们并没有指定socket的room空间,所以当我们从后端发送给前端消息时,所有打开此页面的人,都可以看到我们发送的消息,也就是一个群发功能。
来源:https://blog.csdn.net/bradyM/article/details/127787708


猜你喜欢
- 说明Python语言中列表(List)与其他语言的数组(Array)类似,是一种有序的集合数据结构,Python List可支持各种数据类型
- json_encode()如何转化一个对象? 使用 json_encode() 将数组 array
- 1.元组的概念Python中的元组和列表很相似,元组也是Python语言提供的内置数据结构之一,可以在代码中直接使用。元组和列表就像是一个孪
- 一般开发,SQL Server的数据库所有者为dbo.但是为了安全,有时候可能把它换成其它的名称,所有者变换不是很方便.这里列出两种供参考
- 之道的易搜项目中的搜索分类是通过JS动态生成的,每个生成的元素都要动态的添加属性、事件。其中,添加属性可以采用赋值的方式,这对IE和FF都是
- 1. 简介 在Web应用程序体系架构中,数据持久层(通常是一个关系数据库)是关键的核心部分,它对系统的性能有非常重要的影响。MySQL是目前
- go-cqhttp安装一、 简介1、 介绍官方文档地址:https://docs.go-cqhttp.org/各种框架都只是机器人的各种实现
- 阿里云 视频直播 配置 及 PHP-SDK 接入教程个人感觉,阿里的文档比微信的要坑很多…微信最多是有些比较重要的东西放到比较不起眼、比较难
- 本文实例讲述了python打开文件并获取文件相关属性的方法。分享给大家供大家参考。具体分析如下:下面的代码通过open函数打开文件,并输出文
- 代码如下:'******************************************** '函数名:I
- 登录流程:实例化一个driver,然后driver.get()发送请求最重要的:切换iframe子框架,因为豆瓣的网页中的登录那部分是一个i
- 目录1. 现实背景2. 约定3. 配置 master3.1. 配置启动参数3.2. 重启服务使参数生效3.3. 以 root 身份登录,创建
- 用Python写脚本也有一段时间了,经常操作数据库(MySQL),现在就整理下对各类数据库的操作,如后面有新的参数会补进来,慢慢完善。一,p
- 本文讲述使用JSP实现用户登录,包括用户登录、注册和退出功能等。1.系统用例图2.页面流程图3.数据库设计本例使用oracle数据库创建用户
- 一、继承的格式类的继承格式如下,括号中的为父类名。class 类名(父类名): 代码二、单继承下面我们让Man继承自Master类,并调用继
- 编写聊天程序的服务端代码和客户端代码。完成后,先启动服务端代码,然 后启动客户端程序输人问题,服务端可以返回相应的答案。要求服务端代码具 有
- 基于 python django源码前期准备安装库:pip install django-haystackpip install whoos
- Python内存管理一、对象池1.小整数池系统默认创建好的,等着你使用概述:整数在程序中的使用非常广泛,Python为了优化速度,使用了小整
- 在 HTML 中,有两种方式来表现文本框:一种是使用<input>元素的单行文本框,另一种是使用 <textarea>
- 使用 argparse 模块为应用程序设置命令行选项。有一些第三方库用于命令行解析,但标准库 argparse 与之相比也毫不逊色。无需添加