当前位置: 首页 > news >正文

flask-socketio相关总结

flask-socketio是一个为flask应用程序添加的实时双向通信功能的扩展库,有了这个库,就可以在flask应用中应用websocket协议,帮助flask实现低延迟、双向的客户端、服务端通信。客户端通过任何SocketIO官方库,都能与服务器建立长连接。


文章目录

  • 1、HTTP与WebSocket区别
  • 2、flask-socketio使用
    • 2.1 安装
    • 2.2 关于异步服务的依赖
    • 2.3 flask-socketio简单使用
    • 2.4 服务端接收消息
    • 2.5 服务器发送消息
    • 2.6 广播
    • 2.7 房间
    • 2.8 连接事件
    • 2.9 部署
    • 2.10 跨域问题


1、HTTP与WebSocket区别

HTTP与WebSocket是两种在网络通信中广泛使用的协议,它们各自具有独特的特点和适用场景。

  • HTTP
    定义: HTTP(Hyper Text Transfer Protocol,超文本传输协议)是一个简单的请求-响应协议,通常运行在TCP之上。
    特点: HTTP是基于客户/服务器模式,客户与服务器建立连接后,客户向服务器提出请求,服务器接受请求并作出应答,然后客户与服务器关闭连接。这种连接是一次性的,并且是单向无状态的,每次连接只处理一个请求。HTTP协议传输的数据通常是文本或二进制数据。
    适用场景: 适用于一次性、不会高频更新的数据传输场景,如网页浏览、图片加载等;且由于是无状态协议,因此也非常适合处理大量并发请求,如Web服务器对多个用户的请求进行处理。
  • WebSocket
    定义: WebSocket是一种在单个TCP连接上进行全双工通信的协议。
    特点: WebSocket需要浏览器和服务器握手建立连接。一旦连接建立,客户端和服务器可以双向通信,即服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息。且这种连接是有状态的,连接建立后,客户端和服务器之间的连接将保持活动状态,直到被任何一方(客户端或服务器)终止。WebSocket协议可以传输任意格式的数据,包括文本、二进制、JSON等。
    适用场景: 适用于需要实时性、高频更新的数据传输场景,如在线聊天室、实时股票行情、在线游戏等。由于WebSocket支持双向通信和持久连接,因此非常适合处理需要实时交互的应用场景。

下图是WebSocket与HTTP协议工作图示区别(图片来自迷途小书童的Note):
在这里插入图片描述


2、flask-socketio使用

flask-socketio官方文档链接:https://flask-socketio.readthedocs.io/en/latest/

2.1 安装

flask-socketio可通过pip快速安装:
pip install flask-socketio

2.2 关于异步服务的依赖

flask-socketio需要底层异步服务器的支持,而且会自己根据当前环境存在的异步服务自动选择,可供选择的服务框架有三种,顺序为:eventlet > gevent > werkzeug

  • eventlet,性能最好,支持长轮询和Websocket协议,通过 pip install eventlet 安装。
  • gevent,它能支持多样设置,gevent支持长轮询方式,但是不支持原生WebSocket,为了能支持原生WebSocket,需要选取如下两种方案,一是通过命令 pip install gevent-websocket 安装 gevent-websocket 库为gevent增加WebSocket支持;二是使用带有WebSocket功能的uWSGI Web服务器。性能方面,gevent表现不错,但不如eventlet。
  • 使用基于werkzeug的flask开发服务器,但需要注意的是,它缺乏其他两个选项的性能,因此只应用于简单的开发环境,而且它也仅支持长轮询传输。

2.3 flask-socketio简单使用

首先创建flask应用实例,然后初始化flask-socketio扩展,接着定义事件处理函数,并使用@socketio.on装饰器来监听特定的事件,最后启动应用时,使用socketio.run()来代替app.run()。代码如下:

from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import timeapp = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
socketio = SocketIO()
socketio.init_app(app)@app.route('/')
def index():"""demo page"""return render_template('index.html')  # 用于展示逐字打印效果的网页@socketio.on('start_stream')
def start_stream():text = "这是一段要逐步返回的文字"for char in text:emit('new_char', char)time.sleep(1)if __name__ == '__main__':socketio.run(app, port=5002, debug=True)

前端代码必须加载http://Socket.IO库,并建立连接:

<!DOCTYPE html>
<html><head><script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.2/socket.io.min.js"></script>
</head><body><div id="result"></div><script>const socket = io.connect('http://localhost:5002');socket.on('connect', function () {socket.emit('connect success.');});socket.on('new_char', function (char) {if (char) {document.getElementById('result').innerHTML += char;}});</script>
</body></html>

2.4 服务端接收消息

当使用SocketIO时,消息被双方作为事件接收。前端发送消息时,服务端需要为这些事件注册处理程序。

  • 下面是服务端为一些未命名事件的处理程序:
@socketio.on('message')
def handle_message(data):print('received message: ' + data)    # 未命名事件使用字符串消息@socketio.on('json')
def handle_json(json):print('received json: ' + str(json))   # 未命名事件使用json数据
  • 最灵活的事件类型使用自定义事件名称
# 最灵活的事件类型使用自定义事件名称,比如这里的‘my event’。这些事件的消息数据可以是字符串、字节、int或JSON
@socketio.on('my event')
def handle_my_custom_event(json):print('received json: ' + str(json))# 自定义命名事件也可以支持多个参数
@socketio.on('my_event')
def handle_my_custom_event(arg1, arg2, arg3):print('received args: ' + arg1 + arg2 + arg3)
  • 当装饰的函数名符合python命名规则且不与其他python标识符冲突时,可以用socketio.event装饰器
# 当装饰的函数名符合python命名规则且不与其他python标识符冲突时,可以用socketio.event装饰器,这时不需要指定事件的元数据类型
# 名称message、json、connect和disconnect是保留的,因此不能用于命名事件。
@socketio.event
def my_custom_event(arg1, arg2, arg3):print('received args: ' + arg1 + arg2 + arg3)
  • 命名空间,namespace
# flask-socketio还支持命名空间,所以在不同命名空间下,可以定义相同的事件名,它们不冲突。
# 若未指定命名空间,则使用名称为‘/’的默认全局命名空间
@socketio.on('my event', namespace='/test')
def handle_my_custom_namespace_event(json):print('received json: ' + str(json))
  • 若不想使用装饰器,用socketio的on_event方法调用实现消息的处理
# 不用装饰器语法也可以,用socketio的on_event方法调用实现消息的处理
def my_function_handler(data):passsocketio.on_event('my event', my_function_handler, namespace='/test')
  • 客户端如何确认服务器已经收到了它们发的消息
# 从处理函数返回的任何值都将作为回调函数的参数传递给客户端
# 下面例子中,客户端回调函数将被调用两个参数,‘one’和2。如果处理程序函数不返回任何值,则调用客户端回调函数时不带参数。
@socketio.on('my event')
def handle_my_custom_event(json):print('received json: ' + str(json))return 'one', 2

2.5 服务器发送消息

SocketIO事件处理程序可以使用send()和emit()函数向连接的客户端发送消息。

  • 下面是一些简单的例子,将服务端接收到前端发来的消息再发送回去。其中send用于未命名事件,emit用于命名事件。
from flask_socketio import send, emit@socketio.on('message')
def handle_message(message):send(message)@socketio.on('json')
def handle_json(json):send(json, json=True)@socketio.on('my event')
def handle_my_custom_event(json):emit('my response', json)
  • 命名空间(namespace),Send()和emit()默认使用传入消息的名称空间,当然也可以指定另外不同的命名空间。
@socketio.on('message')
def handle_message(message):send(message, namespace='/chat')@socketio.on('my event')
def handle_my_custom_event(json):emit('my response', json, namespace='/chat')
  • 要用元组包含发送带有多个参数的事件
@socketio.on('my event')
def handle_my_custom_event(json):emit('my response', ('foo', 'bar', json), namespace='/chat')
  • 服务端如何确认客户器已经收到了它们发的消息
def ack():print('message was received!')@socketio.on('my event')
def handle_my_custom_event(json):emit('my response', json, callback=ack)   # 确认回调

2.6 广播

SocketIO的另一个非常有用的特性是消息广播。Flask-SocketIO通过send()和emit()的可选参数broadcast=True来支持此功能。广播功能开启时,所有连接这个命名空间的客户端(包括发送者在内)都会收到这个消息。命名空间未指定时,所有连接全局命名空间的客户端会接收消息。注意,广播消息不会触发回调函数。

@socketio.on('my event')
def handle_my_custom_event(data):emit('my response', data, broadcast=True)
  • 上面的例子都是服务端在接收到客户端发来的消息事件后作出的响应,服务端如何首先给客户端发送消息。
def some_function():socketio.emit('some event', {'data': 42})

这里的socketio.send() 和socketio.emit()方法不同于处在事件函数上下文中的send() 和emit()。另外,由于是在一个普通函数中,没有客户端上下文信息,所以 broadcast=True是默认的,不必指定。


2.7 房间

实际应用场景中,可能需要给用户分组。比如,聊天室,不同用户只能收到他们所在房间的消息。通过join_room() 和 leave_room() 可以实现上述功能:

from flask_socketio import join_room, leave_room@socketio.on('join')
def on_join(data):username = data['username']room = data['room']join_room(room)send(username + ' has entered the room.', to=room)@socketio.on('leave')
def on_leave(data):username = data['username']room = data['room']leave_room(room)send(username + ' has left the room.', to=room)

send()和emit()函数接受to=room用于把消息发送到指定房间。
所有客户端连接时,会被分配一个房间。默认房间名称为连接的session ID,flask中通过request.sid获取该ID。客户端能加入所有存在的房间。客户端断开时,所有它加入的房间都会移除它。上下文外的socketio.send() 和 socketio.emit()也可以接收room参数,来给房间中所有客户端广播。


2.8 连接事件

连接和断开事件用于验证客户端是否有连接权限

@socketio.on('connect')
def test_connect(auth):emit('my response', {'data': 'Connected'})@socketio.on('disconnect')
def test_disconnect():print('Client disconnected')

连接处理程序中的auth参数是可选的。客户端可以使用它来传递字典格式的令牌等身份验证数据。


2.9 部署

  • 内置服务器
    最简单的部署方式,就是安装eventlet或gevent,然后调用socketio.run(app)。需要注意的是,socketio.run(app)是用于生产环境的,但前提必须确保eventlet或gevent已经安装;否则只会调用Flask自带的服务器,这个服务器仅限于测试环境使用。

  • Gunicorn服务器
    使用gunicorn作为web服务器,使用eventlet或gevent工作线程。需要安装gunicorn,eventlet或者gevent。
    通过gunicorn启动eventlet服务器的命令行:gunicorn --worker-class eventlet -w 1 module:app
    通过gunicorn启动gevent服务器的命令行:gunicorn -k gevent -w 1 module:app
    当使用gunicorn与gevent,而且选择由geevent-WebSocket提供的WebSocket支持时,命令行如下:
    gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 module:app
    gunicorn的第三个选择是使用线程工作器,以及用于WebSocket支持的simple-websocket包。对于CPU占用较多的应用程序可以使用:
    gunicorn -w 1 --threads 100 module:app
    所有这些命令,module是python的定义在应用实例当中的包或模块,app就是应用实例本身。

  • uWSGI服务器
    当将uWSGI服务器与gevent结合使用时,Socket.IO服务器可以利用uWSGI的原生WebSocket支持,启动命令如下:
    uwsgi --http :5000 --gevent 1000 --http-websockets --master --wsgi-file app.py --callable app


2.10 跨域问题

如果是前后端分离的系统中,就会出现跨域问题,在网络应用开发中,跨域资源共享(Cross Origin Resource Sharing,简称CORS)是一种机制,允许服务器与指定的来源或域名之间共享资源。使用CORS,我们可以灵活地控制不同域之间的数据传输,实现安全、可靠的跨域访问。单纯在flask应用中,可以使用flask-cors扩展库来实现CORS功能。

# 安装: pip install flask-cors
from flask import Flask, jsonify
from flask_cors import CORSapp = Flask(__name__)
CORS(app) # 允许应用的所有视图都可以跨域访问....

但是在app用flask-socketio中,上述方法并不起作用了,我们需要在 socketio 初始化的时候加入必要的参数来实现跨域访问:

socketio = SocketIO()
socketio.init_app(app, cors_allowed_origins='*')

相关文章:

flask-socketio相关总结

flask-socketio是一个为flask应用程序添加的实时双向通信功能的扩展库&#xff0c;有了这个库&#xff0c;就可以在flask应用中应用websocket协议&#xff0c;帮助flask实现低延迟、双向的客户端、服务端通信。客户端通过任何SocketIO官方库&#xff0c;都能与服务器建立长连接…...

2024-12-03OpenCV图片处理基础

OpenCV图片处理基础 OpenCV的视频教学&#xff1a;https://www.bilibili.com/video/BV14P411D7MH 1-OpenCV摄像头读取 OpenCV使用摄像头读取图片帧&#xff0c;点击S保存当前帧到指定文件夹&#xff0c;点击Q关闭窗口&#xff0c;点击其他按钮打印按钮的值 要实现这个功能&…...

本地部署开源趣味艺术画板Paint Board结合内网穿透跨网络多设备在线绘画

文章目录 前言1.关于Paint Board2.本地部署paint-board3.使用Paint Board4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定Paint Board公网地址 前言 大家好&#xff0c;是不是每次想要在电脑上画画时&#xff0c;都被那些笨重的专业绘图软件搞得头大如斗呢&#xff1f;…...

iOS、android的app备案超简单的公钥、md5获取方法

很多云商的备案平台&#xff0c;推荐下载一些工具来获取公钥和MD5&#xff0c;但是这些工具的跨平台性不是很好&#xff0c;安装也十分麻烦&#xff0c;安装的时候还需要设置国内源等等。 这里&#xff0c;其实有在线工具可以获取APP的公钥和MD5、SHA1值这些信息的。不需要安装…...

SpringCloud 与 SpringBoot版本对应关系,以及maven,jdk

目录 SpringCloud 与 SpringBoot各版本的对应关系 方式一 Learn 方式二 OverView SpringBoot与JDK、maven 容器等对应关系 SpringCloud 与 SpringBoot各版本的对应关系 SpringCloudSpringBootFinchley2.0.xFinchley.SR1Spring Boot >=2.0.3.RELEASE and <=2.0.9RELEAS…...

23种设计模式之装饰模式

目录 1. 简介2. 代码2.1 ABatterCake &#xff08;抽象组件&#xff09;2.2 BatterCake &#xff08;具体组件&#xff09;2.3 ADecorator &#xff08;抽象装饰者&#xff09;2.4 EggDecorator &#xff08;具体装饰者&#xff09;2.5 SausageDecorator&#xff08;具体装饰者…...

HTMLHTML5革命:构建现代网页的终极指南 - 2. HTMLHTML5H5的区别

HTML&HTML5革命&#xff1a;构建现代网页的终极指南 2. HTML&HTML5&H5的区别 大家好&#xff0c;我是莫离老师 在上一节课&#xff0c;我们了解了HTML的重要性和前端开发的核心概念。 今天&#xff0c;我们将深入探讨 HTML、HTML5 和 H5 的区别&#xff0c;并重点…...

Django之ORM表操作

ORM表操作 1.ORM单表操作 首先想操作表的增删改查&#xff0c;需要先导入这个表,以之前创建的UserInfo表为例,在app下的views.py中导入 from app import modelsdef query(request):new_obj models.UserInfo(id1,name北北,bday2019-09-27,checked1,)new_obj.save()return Htt…...

python下几个淘宝、天猫、京东爬虫实例

以下是使用Python编写的针对淘宝、天猫、京东详情页的爬虫实例。请注意&#xff0c;这些实例仅供参考&#xff0c;实际使用时可能需要根据网站结构的变化进行调整&#xff0c;并且需要遵守各平台的爬虫协议和法律法规。 淘宝详情页爬虫实例 环境准备&#xff1a; Python 3.xSe…...

级联树结构TreeSelect和上级反查

接口返回结构 前端展示格式 前端组件 <template><div ><el-scrollbar height"70vh"><el-tree :data"deptOptions" :props"{ label: label, children: children }" :expand-on-click-node"false":filter-node-me…...

gradle下载慢解决方案2024 /12 /1android studio (Windows环境)

gradle下载慢解决方案2024 /12 /1 默认环境配置好了,环境配置和程序安装请出门右转 打开软件,点击右上角设置,找到如下设置页 选择本地安装并制定好你已经安装好的 gradle 应用保存即可 全局插件环境配置(新版本可以直接在设置中添加了) 找对应位置添加国内源并把前面的内置源…...

Python+OpenCV系列:GRAY BGR HSV

以下是 GRAY、BGR 和 HSV 三种色彩空间的对比&#xff0c;涵盖了它们的定义、特点、应用场景和优缺点&#xff1a; 1. 定义 GRAY&#xff1a; 灰度图像仅包含亮度信息&#xff0c;每个像素用一个值&#xff08;通常在0到255之间&#xff09;表示亮度&#xff08;黑到白&#x…...

丢垃圾视频时间检测 -- 基于状态机的实现

文章目录 OverviewKey PointsPseudo-code Overview 需要考虑的方面 状态定义和转换条件时序约束空间约束异常处理 状态机的设计需要考虑的场景&#xff1a; 没有人人进入人携带垃圾人离开但垃圾留下垃圾消失异常情况&#xff08;检测失败、多人多垃圾等&#xff09; Key P…...

【QT】一个简单的串口通信小工具(QSerialPort实现)

目录 0.简介 1.展示结果 1&#xff09;UI界面&#xff1a; 2&#xff09;SSCOM&#xff08;模拟下位机收发&#xff09;&#xff1a; 3&#xff09;VSPD虚拟串口驱动&#xff08;连接上位机和下位机的串口&#xff09;&#xff1a; 4&#xff09;实际收发消息效果及视频演…...

24/12/5 算法笔记<强化学习> doubleDQN,duelingDQN

我们前面了解了DQN网络的一些知识&#xff0c;然而DQN还有一些改进的方法&#xff0c;比如doubleDQN和duelingDQN,我们先来将一下doubleDQN和DQN. 先来对比一下 单一网络 vs. 双重网络 DQN:是一个深度神经网络来估计每个动作的Q值 DDQN:使用两个独立的深度神经网络&#xf…...

道可云人工智能元宇宙每日资讯|全国工商联人工智能委员会成立会议在南京举办

道可云元宇宙每日简报&#xff08;2024年12月5日&#xff09;讯&#xff0c;今日元宇宙新鲜事有&#xff1a; 全国工商联人工智能委员会成立会议在南京举办 全国工商联人工智能委员会成立会议日前在江苏省南京市举办。中央统战部副部长、全国工商联党组书记沈莹出席会议并讲话…...

MySQL数据库(2)-检查安装与密码重置

1. 数据库下载安装 下载地址&#xff1a;MySQL :: Download MySQL Community Server 2. My.ini配置文件 my.ini 文件通常在MySQL安装过程中自动创建&#xff0c; 并且可以根据需要进行编辑以调整服务器的行为。 3. 配置环境变量 4. 查询版本号 查询版本号&#xff1a;mysql…...

C# 13 中的新增功能

C# 12 中的新增功能C# 11 中的新增功能C# 10 中的新增功能C# 9.0 中的新增功能C# 8.0 中的新增功能C&#xff03;7.0中有哪些新特性&#xff1f;C#6.0中10大新特性的应用和总结C# 5.0五大新特性 将C#语言版本升级为预览版 C# 13 包括一些新增功能。 可以使用最新的 Visual Stu…...

视频自学笔记

一、视频技术基本框架 二、视频信号分类 2.1信号形式 2.1.1模拟视频 模拟视频是指由连续的模拟信号组成的视频图像&#xff0c;以前所接触的电影、电视都是模拟信号&#xff0c;之所以将它们称为模拟信号&#xff0c;是因为它们模拟了表示声音、图像信息的物理量。摄像机是获…...

easyexcel 导出日期格式化

1.旧版本 在新的版本中formate已经被打上废弃标记。那么不推荐使用这种方式。 2.推荐方式 推荐使用另外一种方式【 Converter 】代码如下&#xff0c;例如需要格式化到毫秒【yyyy-MM-dd HH:mm:ss SSS】级别 创建一个公共Converter import com.alibaba.excel.converters.Conv…...

02-开发环境搭建

02-开发环境搭建 鸿蒙开发环境的准备主要分为以下环节&#xff1a; 注册开发者实名认证创建应用下载安装开发工具新建工程 注册开发者 在华为开发者联盟网站上&#xff0c;注册成为开发者&#xff0c;并完成实名认证。 打开华为开发者联盟官网&#xff0c;点击“注册”进入…...

DBeaver导入csv到数据库

DBeaver的图标是一只小浣熊&#xff0c;查了下Beaver确实是浣熊的意思&#xff0c;看起来还是蛮可爱的。 业务上有需要导入csv到数据库的需求&#xff0c;试用了下&#xff0c;发现挺好用的。有很多属性可以定制。 导入步骤&#xff1a; 1.建表&#xff0c;表字段与待导入cs…...

React第十一节 组件之间通讯之发布订阅模式(自定义发布订阅器)

组件之间通讯常用方案 1、通过props 2、通过context 3、通过发布订阅模式 4、通过Redux 后面会有专栏介绍 什么情况下使用发布订阅模式 a、当我们想要兄弟组件之间通讯&#xff0c;而共同的父组件中又用不到这些数据时候&#xff1b; b、当多个毫无相关的组件之间想要进行数据…...

tcpreplay/tcpdump-重放网络流量/捕获、过滤和分析数据包

tcpdump 是一个网络数据包分析工具&#xff0c;通过捕获并显示网络接口上传输的数据包&#xff0c;帮助用户分析网络流量。 原理&#xff1a;用户态通过 libpcap 库控制数据包捕获&#xff0c;内核态通过网卡驱动获取数据包。 核心功能包括&#xff1a;捕获、过滤和分析数据包…...

ASPICE评估体系概览:对象、范围与参考标准解析

ASPICE&#xff08;汽车软件过程改进和能力确定&#xff09;是一个框架&#xff0c;它被广泛应用于汽车行业的软件开发和维护过程的改进。 它类似于软件工程领域的CMMI&#xff08;能力成熟度模型集成&#xff09;&#xff0c;但专门针对汽车行业&#xff0c;考虑了该行业特有…...

力扣92.反转链表Ⅱ

题目描述 题目链接92. 反转链表 II 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left …...

Java设计模式之适配器模式:深入JDK源码探秘Set类

在Java编程中&#xff0c;Set类作为一个不允许存储重复元素的集合&#xff0c;广泛应用于数据去重、集合运算等场景。然而&#xff0c;你是否曾好奇Set类是如何在底层实现元素唯一性判断的&#xff1f;这背后隐藏的力量正是适配器模式。 适配器模式简介 适配器模式&#xff0…...

java八股-流量封控系统

文章目录 请求后台管理的频率-流量限制流量限制的业务代码UserFlowRiskControlFilter 短链接中台的流量限制CustomBlockHandler 对指定接口限流UserFlowRiskControlConfigurationSentinelRuleConfig 请求后台管理的频率-流量限制 根据登录用户做出控制&#xff0c;比如 x 秒请…...

【WebRTC】Android SDK使用教学

文章目录 前言PeerConnectionFactoryPeerConnection 前言 最近在学习WebRTC的时候&#xff0c;发现只有JavaScript的API文档&#xff0c;找了很久没有找到Android相关的API文档&#xff0c;所以通过此片文章记录下在Android应用层如何使用WebRTC 本篇文章结合&#xff1a;【W…...

基于单片机的智能晾衣控制系统的设计与实现

摘要:本文是以 AT89C52 单片机为核心来实现智能晾衣控制系统。在这个系统中,雨水检测传感器是用来检测出雨的,而控制器将检测信号的变换,根据变换后的信号自动驱动直流电机将被风干 的棒收回,以便随时控制直流电机来实现晾衣;在光敏模块中检测昼夜的环境,自动控制晾衣杆…...