Flask和Vue框架实现WebSocket消息通信

1 安装环境

1.1 安装Flask环境

主要的安装包 Flask、Flask-SocketIO,注意Python版本要求3.6+

# Flask-SocketIO参考地址
https://flask-socketio.readthedocs.io/en/latest/
https://github.com/miguelgrinberg/flask-socketio

更新基础环境

# 更新pip
python -m pip install --upgrade pip# 更新setuptools
pip install --upgrade setuptools# 安装Flask
pip install flask
pip install flask_cors# 安装关于SocketIO的包
# 安装python-socketio时,会自动安装python-engineio依赖
pip install python-socketio
pip install flask-socketio# eventlet具有WSGI支持的异步框架,主要功能是通过协程实现并发
pip install eventlet

我的“requirements.txt”的包

bidict==0.22.1
blinker==1.7.0
click==8.1.7
colorama==0.4.6
dnspython==2.4.2
eventlet==0.33.3
Flask==3.0.0
Flask-Cors==4.0.0
Flask-SocketIO==5.3.6
greenlet==3.0.1
h11==0.14.0
importlib-metadata==7.0.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
python-engineio==4.8.0
python-socketio==5.10.0
simple-websocket==1.0.0
six==1.16.0
Werkzeug==3.0.1
wsproto==1.2.0
zipp==3.17.0

安装命令

pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

1.2 安装Vue环境

(1)使用vite创建项目

# 创建项目
npm create vite@latest# 选择框架和语言,我选择的是Vue和TypeScript
√ Project name: ... websocket
√ Select a framework: » Vue
√ Select a variant: » TypeScriptDone. Now run:cd websocketnpm installnpm run dev# 进入目录
cd websocket# 安装相关包
npm install
# 安装包结束后提示如下:
added 44 packages, and audited 45 packages in 14s

(2)安装依赖包

# 安装一个包即可
npm install socket.io-client -S

socket.io-client的参考地址

https://socket.io/docs/v4/client-api/

查看npm包版本和例子的网络地址

https://www.npmjs.com/

备注:npm中命令参数的意思

--global(-g):表示全局全局安装,包安装在了node目录下的node_modules/npm中(可以在任意项目中使用该工具);不使用-g安装,包安装在了工程目录下的node_modules中下。
--save(-S):表示写入package.json文件中的dependencies,这里面的包是发布到生产环境中的,例如:vue、axios等。
--save-dev(-D):表示写入package.json文件中的devDependencies,这里面的包是仅在开发环境中辅助开发,在生产环境中不需要,例如:vite、css-loader等。
不使用参数时:npm使用的是--save(-S)命令

package.json文件

{"name": "websocket","private": true,"version": "0.0.0","type": "module","scripts": {"dev": "vite","build": "vue-tsc && vite build","preview": "vite preview"},"dependencies": {"socket.io-client": "^4.7.2","vue": "^3.3.8"},"devDependencies": {"@types/node": "^20.10.2","@vitejs/plugin-vue": "^4.5.0","typescript": "^5.2.2","vite": "^5.0.0","vue-tsc": "^1.8.22"}
}

(3)使用Vscode常见报错

报错1

Cannot find module './App.vue' or its corresponding type declarations.ts(2307)

解决方法

修改项目根目录中 “env.d.ts” 文件,添加如下内容:

/// <reference types="vite/client" />
declare module "*.vue" {import { DefineComponent } from "vue"const component: DefineComponent<{}, {}, any>export default component
}

报错2

Module xx.vue has no default export.Vetur(1192)

解决方法

卸载vetur插件,主要针对vue2项目;
安装Volar插件,全称Vue Language Features (Volar),主要针对vue3和TypeScript项目;

报错3

使用“@”无法导入ts文件,错误符号指向“@”,Cannot find module 'XXXXs' or its corresponding type declarations

解决方法

  • 安装@types/node,会在项目中生成一个vite-env.d.ts文件
npm i @types/node -D
  • 在vite.config.js文件中配置参数
import  defineConfig ] from 'vite';
import vue from '@vitejs/plugin-vue'import path from "path";export default defineConfig({plugins: [vue()],resolve: {// !!!!配置路径别名!!!alias: {'@': path.resolve(__dirname,'./src'),}},
});
  • 在 tsconfig.json中配置代码
"compilerOptions":{"baseUrl": "./","paths":{"@": ["src"],"@/*": ["src/*"],}
}

(4)启动服务

在vscode中打开,在doc上启动服务

npm run dev

1.3 版本要求

flask-socketio的版本兼容

JavaScript Socket.IO versionSocket.IO protocol revisionEngine.IO protocol revisionFlask-SocketIO versionpython-socketio versionpython-engineio version
0.9.x1, 21, 2Not supportedNot supportedNot supported
1.x and 2.x3, 434.x4.x3.x
3.x and 4.x545.x5.x4.x

1.4 Flask-SocketIO消息隔离

我认为有三种隔离级别

隔离级别对应策略说明
全局/全局命名空间,连接到此命名空间下的客户端会收到消息,系统默认空间
空间namespace特定命名空间,连接到此命名空间的客户端会收到消息,不同命名空间相互隔离
room在某命名空间下的用户组,不同用户组仅仅接收自己所在组的消息,不同组消息隔离

2 Flask项目

2.1 项目布局

在这里插入图片描述

2.2 源代码

main.py

from blueprint_user import init_blueprint
from config_app import socketio, app# 初始化蓝本
from socket_comm import init_socketinit_blueprint()init_socket()if __name__ == '__main__':socketio.run(app, host='0.0.0.0', port=5000, debug=True)

config_app.py

from flask import Flask
from flask_cors import CORSfrom flask_socketio import SocketIOdef create_app():flask_app = Flask(__name__)# 设置密钥flask_app.config['token'] = '123456'CORS(flask_app, supports_credentials=True)return flask_appdef create_socketio():flask_socketio = SocketIO()# 解决跨域问题flask_socketio.init_app(app, cors_allowed_origins='*')return flask_socketioapp = create_app()socketio = create_socketio()name_space_user = "/user"

blueprint_user.py

from flask import Blueprintfrom config_app import app, name_space_user, socketiouser = Blueprint("user", __name__)# 注册蓝本
def init_blueprint():app.register_blueprint(user, url_prefix='/user')@user.route('/')
def index():return "Success"# 使用方法传递参数
@user.route('/broad')
def broad_event():event_name = "data_res"broad_casted_data = {'data': "test message!"}# 发送消息socketio.emit(event_name, broad_casted_data, namespace=name_space_user)return "success"

socket_comm.py

from flask_socketio import emit, send, join_room, leave_roomfrom config_app import socketio, name_space_userdef init_socket():pass# 可以用“@socketio.event”替代“@socketio.on('connect')”
# “@socketio.event”可以用来装饰socketio默认的事件,例如:connect等
@socketio.on('connect', namespace=name_space_user)
def connected_msg(auth:dict):print(auth)print('client connected.')if(auth.get("token") == "123"):return Trueelse:return False@socketio.on('disconnect', namespace=name_space_user)
def disconnect_msg():print('client disconnected.')@socketio.on('data_event', namespace=name_space_user)
def test_event(message):print(message)# emit(): 发送到指定活动上,对应前端的data_res"""# 对应前端的代码socket.on('data_res', (data:string) => {console.log('监听消息:');console.log(data);});"""emit('data_res', message, broadcast=True)@socketio.on('data_msg', namespace=name_space_user)
def test_msg(message):print(message)# send(): 发送到message,对应前端的message"""# 对饮前端的代码socket.on("message", function(data: string){console.log("Message" + data)})"""send(message, namespace=name_space_user, broadcast=True)@socketio.on('join', namespace=name_space_user)
def on_join(data):username = data['username']room = data['room']join_room(room)print(data)send(username + ' has entered the room.', to=room)@socketio.on('leave', namespace=name_space_user)
def on_leave(data):username = data['username']room = data['room']leave_room(room)print(data)send(username + ' has left the room.', to=room)@socketio.on('send_room', namespace=name_space_user)
def send_room(data):username = data['username']room = data['room']print(data)send(data, to=room)

3 Vue项目

构建项目使用的是“组合式 API (Composition API)”编写,不是“选项式 API (Options API)”

3.1 项目布局

在这里插入图片描述

3.2 源代码

main.ts

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'createApp(App).mount('#app')

vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'import path from "path";// https://vitejs.dev/config/
export default defineConfig({// 配置插件列表plugins: [vue()],resolve: {// !!!!配置路径别名!!!alias: {'@': path.resolve(__dirname,'./src'),},},// 打包配置build: {target: 'modules',// 设置输出路径outDir: 'dist'},// 本地运行配置,及反向代理配置server: {// 默认启用并允许任何源cors: true,// 使用默认浏览器中打开应用程序open: true,// 设置本地端口port: 4000,// 在本地开发环境中,设置反向代理配置,注意配置rewriteproxy: {// '/api': {//   // 设置代理接口访问实际地址//   target: 'http://localhost/5000',//   changeOrigin: true,//   // 允许websocket代理//   ws: true,//   // 将api替换为空//   rewrite: (path) => path.replace(/^\/api/, '')// },// '/socket.io': {//   target: `ws://127.0.0.1:5000`,//   ws: true,//   changeOrigin: true//  },}}
})

App.vue

<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
</script><template><div class="app"><HelloWorld msg="app" /></div></template><style scoped>
.app{width: 100%;height: 100%;
}
</style>

在”config/ws“目录下:

index.ts


/*import { io } from 'socket.io-client';// 第一种连接方法
// 参考地址:https://socket.io/docs/v4/client-api/#io
export function create_socket(token: string) {const socket = io('http://127.0.0.1:5000', {// 指定传输方式,如WebSocket    transports: ['websocket'],// 是否自动连接autoConnect: true,// 是否自动重新连接reconnection: true,// 重新连接尝试次数reconnectionAttempts: 3,// 重新连接延迟时间(毫秒)reconnectionDelay: 1000,// 自定义查询参数// query: {//     token: token// },// 其他可选参数...});return socket;
}*/// 第二种连接方法
// 参考地址:https://socket.io/docs/v4/client-api/#manager
import { Manager } from "socket.io-client";export function create_socket(token: string) {const manager = new Manager("ws://127.0.0.1:5000", {// 指定传输方式,如WebSocket    transports: ['websocket'],// 是否自动连接autoConnect: true,// 是否自动重新连接reconnection: true,// 重新连接尝试次数reconnectionAttempts: 3,// 重新连接延迟时间(毫秒)reconnectionDelay: 1000,// 自定义查询参数// query: {//     token: token// },// 其他可选参数...});const socket = manager.socket("/user", {auth: {token: token}});return socket
}

在”components“目录下:

HelloWorld.vue

<script setup lang="ts">
import { ref, onMounted } from 'vue'import { create_socket } from '@/config/ws/index.ts';
const socket = create_socket("123");defineProps<{ msg: string }>()function re_open_conn(){// // 第一种方法连接let connect_res = socket.open();console.log(connect_res)// console.log(connect_res.connected)// 第二种方法连接// 默认通道 connect是通道名称// socket.on('connect', () => {//   console.log('连接成功');// });
}function close_conn(){// 关闭连接,disconnect_res是一个Socket对象// socket.disconnect()和socket.close()作用相同// 对应后端的代码// @socketio.on('disconnect', namespace=name_space_user)let disconnect_res = socket.disconnect()console.log(disconnect_res)// 下面这种方法后端没反应// socket.on("disconnect", () => {//   console.log("关闭连接")// });
}// 响应式状态
let msg = ref("测试")function send_msg(){console.log("data_event" + msg.value)socket.emit("data_event", "Event " + msg.value)console.log(" data_msg "+ msg.value);socket.emit("data_msg", "Message " + msg.value)
}// 更改状态、触发更新的函数
function listen_event() {socket.on('data_res', (data:string) => {console.log('监听事件(event)-对应后端emit()方法');console.log(data);});socket.on("message", function(data:string){console.log("监听消息(message)-对应后端send()方法:")console.log(data)});}onMounted(()=>{listen_event()
});function join_room(){socket.emit("join", {"username":"zhangsan", "room":"room1"})
}function leave_room(){socket.emit("leave", {"username":"zhangsan", "room":"room1"})
}function send_room(){socket.emit("send_room", {"username":"zhangsan", "room":"room1"})
}</script><template><div class="hello"><button v-on:click="re_open_conn">打开连接</button><button v-on:click="close_conn">关闭连接</button><button v-on:click="send_msg">发送消息</button><input v-model="msg"/><br/><button v-on:click="join_room">进入房间</button><button v-on:click="leave_room">离开房间</button><button v-on:click="send_room">房间发送消息</button></div>
</template><style scoped>
.hello {color: #888;
}
</style>

index.html

<!doctype html>
<html lang="en"><head><meta charset="UTF-8" /><link rel="icon" type="image/svg+xml" href="/vite.svg" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Vite + Vue + TS</title></head><body><div id="app"></div><script type="module" src="/src/main.ts"></script></body>
</html>

4 运行结果

前端

在这里插入图片描述

后端
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/212659.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

以太坊虚拟机EVM介绍,智能合约详解

以太坊为例&#xff1a;什么是智能合约&#xff1f;智能合约怎么部署、调用、执行&#xff1f;智能合约的原理&#xff1f;智能合约存在哪儿&#xff1f;如何区分调用的是智能合约&#xff1f;世界状态数据库、EVM、智能合约它们之间的关系&#xff1f; 什么是智能合约 指的是…

【Hive】启动beeline连接hive报错解决

1、解决报错2、在datagrip上连接hive 1、解决报错 刚开始一直报错&#xff1a;启动不起来 hive-site.xml需要配置hiveserver2相关的 在hive-site.xml文件中添加如下配置信息 <!-- 指定hiveserver2连接的host --> <property><name>hive.server2.thrift.bin…

机器人与3D视觉 Robotics Toolbox Python 二 空间位姿描述

空间位姿描述 二维空间位姿描述 二维空间位姿表示方法 from spatialmath.base import * from spatialmath import * T1 SE2(x3,y3,theta30,unit"deg") trplot2(T1.A,frame"T1",dims[0, 5, 0, 5]) T2transl2(3, 4) trplot2(T2,frame"T2",dims…

如何理解 RPC 远程服务调用?

本文主要讲解 RPC 远程服务调用相关的知识。 RPC 远程服务调用是分布式服务架构的基础&#xff0c;无论微服务设计上层如何发展&#xff0c;讨论服务治理都绕不开远程服务调用&#xff0c;那么如何理解 RPC、有哪些常见的 RPC 框架、实现一款 RPC 框架需要哪些技术呢&#xff…

解决electron修改主进程后需要重启才生效

nodemon 是一种工具&#xff0c;可在检测到目录中的文件更改时通过自动重新启动节点应用程序来帮助开发基于 node.js 的应用程序 nodemon 特性 自动重新启动应用程序。检测要监视的默认文件扩展名。默认支持 node&#xff0c;但易于运行任何可执行文件&#xff0c;如 python、…

自动驾驶学习笔记(十七)——视觉感知

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo 社区开发者圆桌会》免费报名—>传送门 文章目录 前言 分类 目标检测 语义分割 实例分割 …

SQL语句的执行顺序怎么理解?

SQL语句的执行顺序怎么理解&#xff1f; 我们常常会被SQL其书写顺序和执行顺序之间的差异所迷惑。理解这两者的区别&#xff0c;对于编写高效、可靠的SQL代码至关重要。今天&#xff0c;让我们用一些生动的例子和场景来深入探讨SQL的执行顺序。 一、书写顺序 VS 执行顺序 SQ…

【unity实战】一个通用的FPS枪支不同武器射击控制脚本

文章目录 前言模型素材文章用到的粒子火光特效射击效果换弹瞄准开枪抖动效果设置显示文本最终代码不同武器射击效果1. 手枪2. 机枪3. 狙击枪4. 霰弹枪5. 加特林 其他感谢完结 前言 实现FPS枪支不同武器效果&#xff0c;比如手枪&#xff0c;喷子&#xff0c;狙击枪&#xff0c…

《使用ThinkPHP6开发项目》 - 创建应用

《使用ThinkPHP6开发项目》 - 安装ThinkPHP框架-CSDN博客 《使用ThinkPHP6开发项目》 - 设置项目环境变量-CSDN博客 《使用ThinkPHP6开发项目》 - 项目使用多应用开发-CSDN博客 根据前面的步骤&#xff0c;我们现在就可以开发我们的项目开发了&#xff0c;根据项目开发的需要…

【数据挖掘】国科大苏桂平老师数据库新技术课程作业 —— 第四次作业

云数据库研究 云计算与云数据库背景 云计算&#xff08;cloud computing&#xff09;是 IT 技术发展的最新趋势&#xff0c;正受到业界和学术界的广泛关注。云计算是在分布式处理、并行处理和网格计算等技术的基础上发展起来的&#xff0c;是一种新兴的共享基础架构的方法。它…

[足式机器人]Part4 南科大高等机器人控制课 Ch05 Instantaneous Velocity of Moving Frames

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;CLEAR_LAB 笔者带更新-运动学 课程主讲教师&#xff1a; Prof. Wei Zhang 南科大高等机器人控制课 Ch05 Instantaneous Velocity of Moving Frames 1.Instantanenous Velocity of Rotating Frames2.Instantanenous Veloc…

最新Redis7持久化(权威出版)

首先我们要知道什么是持久化&#xff1a;持久化是指将数据保存到磁盘上&#xff0c;以确保在Redis服务器重启时数据不会丢失。 Redis支持两种主要的持久化方式&#xff1a;RDB持久化和AOF持久化 下面让我依次给你介绍一下&#xff1a; RDB持久化 作用 这是将Redis数据保存…

Java语言概述及保姆级入门教程(JDK 17版本)

笔记来自尚硅谷老师-康老师 学习教程&#xff1a;https://www.bilibili.com/video/BV1PY411e7J6/?spm_id_from333.337.search-card.all.click 1、Java基础全程脉络图 1.1 本章专题与脉络 2. 抽丝剥茧话Java 2.1 当前大学生就业形势 麦可思研究院发布了《2022年中国大学生就业…

C#图像处理OpenCV开发指南(CVStar,09)——边缘识别之Scharr算法的实例代码

1 边缘识别之Scharr算法 算法文章很多&#xff0c;不再论述。 1.1 函数原型 void Cv2.Scharr(src,dst,ddepth,dx,dy,scale,delta,borderType&#xff09; 1.2 参数说明 src 代表原始图像。dst 代表目标图像。ddepth 代表输出图像的深度。CV_16Sdx 代表x方向上的求导阶数…

uniApp应用软件在运行时,不符合华为应用市场审核标准。解决方案合集!

&#xff08;暂时用不到的也建议收藏一下&#xff0c;因为文章持续更新中&#xff09; 最新更改时间&#xff1a;20023-12-10 第一次做App应用开发相信大家一定都遇到过华为应用市场审核的“驳回”&#xff01; 有些问题一看就明白可以立马修改&#xff0c;而有一些问题修改意…

Dubbo入门直接上手,结合微服务详解

Dubbo 高性能、轻量级的 Java RPC 框架 RPC&#xff1a; Remote Procedure Call 远程过程调用&#xff0c;简单来说就是它允许一个计算机程序通过网络请求调用另一个计算机上的程序&#xff0c;就像本地调用一样。有非常多的协议和技术来都实现了RPC的过程&#xff0c;比如&a…

Elasticsearch 8.9 refresh刷Es缓冲区的数据到Lucene,更新segemnt,使数据可见

一、相关API的handler1、接受HTTP请求的hander(RestRefreshAction)2、往数据节点发送刷新请求的action(TransportRefreshAction)3、数据节点接收主节点refresh传输的action(TransportShardRefreshAction) 二、在IndexShard执行refresh操作1、根据入参决定是使用lucene提供的阻塞…

【设计模式--创建型--原型模式】

设计模式--创建型--原型模式 原型模式概述结构实现结果 案例代码结果使用场景 扩展&#xff08;深\浅克隆&#xff09;浅克隆演示&#xff1a;结果&#xff1a;使用深克隆&#xff08;利用对象流&#xff09;结果 原型模式 概述 用一个已经创建的实例作为原型&#xff0c;通过…

Spring Cloud Gateway + Nacos + LoadBalancer实现企业级网关

1. Spring Cloud Gateway 整合Nacos、LoadBalancer 实现企业级网关 前置工作&#xff1a; 创建 SpringBoot 多模块项目创建网关&#xff08;gateway-service&#xff09;、用户&#xff08;user-service&#xff09;模块用户模块添加 Nacos discovery 支持以及 Spring Web&am…

gitbash下载安装

参考教程 零、下载 官网地址 2.43.0win64 链接&#xff1a;https://pan.baidu.com/s/16urs_nmky7j20-qNzUTTkg 提取码&#xff1a;7jaq 一、安装 图标组件&#xff08;Additional icons&#xff09;&#xff1a;选择是否创建桌面快捷方式&#xff1b;桌面浏览&#xff08;Win…