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.pswp.cn/news/212659.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/212659.shtml
英文地址,請注明出處:http://en.pswp.cn/news/212659.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Unity發布WebGL測試界面處理方式參考

如果使用Unity發布WebGL經常會和網頁進行交互&#xff0c;為了能夠做到界面統一&#xff0c;往往所有UI都是在頁面上開發的&#xff0c;Unity本身不做任何UI或者只做三維UI&#xff0c;但是在開發過程中&#xff0c;為了測試接口&#xff0c;難免要在Unity中做一些UI來方便測試…

以太坊虛擬機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;是一種新興的共享基礎架構的方法。它…

Django多對多ManyToManyField字段

Django是一個支持多對多關系的Web框架&#xff0c;可以在模型中定義多對多關系。多對多關系通常涉及兩個實體之間的復雜交互&#xff0c;例如用戶和組之間的關系&#xff0c;或者課程和學生之間的關系。在Django中&#xff0c;可以使用ManyToManyField字段來定義多對多關系。 …

[足式機器人]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…

機器學習基礎入門

機器學習 引言 介紹機器學習的重要性和應用領域。簡要說明機器學習與人工智能的關系。 在當今迅速發展的技術世界中&#xff0c;機器學習已經成為一項不可或缺的技術&#xff0c;它正在改變我們解決問題和理解世界的方式。機器學習&#xff0c;作為人工智能&#xff08;AI&a…

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

首先我們要知道什么是持久化&#xff1a;持久化是指將數據保存到磁盤上&#xff0c;以確保在Redis服務器重啟時數據不會丟失。 Redis支持兩種主要的持久化方式&#xff1a;RDB持久化和AOF持久化 下面讓我依次給你介紹一下&#xff1a; RDB持久化 作用 這是將Redis數據保存…

Java8新特性 - Stream

一、特性 Java 8引入的Stream API為集合&#xff08;Collections&#xff09;提供了一種聲明式的處理方式&#xff0c;支持豐富的操作&#xff0c;包括篩選、映射、歸約等。以下是一些Stream的主要功能和使用方式的案例&#xff1a; 創建Stream&#xff1a; List<String&…

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年中國大學生就業…

TCP 和UDP 到底有啥區別

TCP&#xff08;傳輸控制協議&#xff09;和UDP&#xff08;用戶數據報協議&#xff09;是互聯網上常用的兩種傳輸層協議&#xff0c;它們在數據傳輸方式和特性上有顯著的區別。下面是TCP和UDP的主要區別&#xff1a; 連接性: TCP 是一種面向連接的協議。在數據傳輸前&#xf…

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;而有一些問題修改意…