由于时效问题,该文某些代码、技术可能已经过期,请注意!!!本文最后更新于:1 年前
使用websocket打通 react 和 fastapi
前端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import React, { useEffect, useState } from "react"; import io from "socket.io-client";
const Monitor() = () => { const [cpuUsage, setCpuUsage] = useState(""); const socketRef = React.useRef(null);
useEffect(() => { socketRef.current = io("http://127.0.0.1:1080");
socketRef.current.on("cpu_usage", (data) => { setCpuUsage(data); });
socketRef.current.on("connect", () => { socketRef.current.emit("start_cpu_monitor"); });
return () => { socketRef.current.emit("stop_cpu_monitor"); socketRef.current.disconnect(); }; }, []);
return ( <div className="child1-content"> <p>CPU Usage: {cpuUsage}</p> </div> ); };
export default Monitor;
|
后端代码 test.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import sys import socketio from fastapi import FastAPI from fastapi.staticfiles import StaticFiles import psutil
app = FastAPI()
sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins='*') socket_app = socketio.ASGIApp(sio, static_files={ '/': './react-socketio/build' })
app.mount("/", socket_app)
@sio.event async def connect(sid, environ): print('connected', sid) cpu_percent = psutil.cpu_percent(interval=1) print('Initial CPU Usage:', cpu_percent) await sio.emit('cpu_usage', cpu_percent)
@sio.event async def disconnect(sid): print('disconnected', sid)
async def cpu_monitor(): while running: cpu_percent = psutil.cpu_percent(interval=1) await sio.emit('cpu_usage', cpu_percent) await sio.sleep(1)
@sio.on('start_cpu_monitor') async def start_cpu_monitor(sid): print('Starting CPU monitor...') global running running = True sio.start_background_task(cpu_monitor)
@sio.on('stop_cpu_monitor') async def stop_cpu_monitor(sid): print('Stopping CPU monitor...') global running running = False
if __name__ == '__main__': uvicorn.run(app, host="0.0.0.0", port=8000)
|
后端启动命令
PS:上述后端代码中 socket_app 是挂载在根目录的,这样如果fastapi有其他路由,前端请求会404。所以要解决这个问题,socket_app 就不能挂载在根目录
修改后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| import sys import socketio from fastapi import FastAPI, BackgroundTasks, Request from fastapi.staticfiles import StaticFiles import psutil
app = FastAPI() sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins='*') socket_app = socketio.ASGIApp(sio)
app.mount("/ws", socket_app)
@sio.event async def connect(sid, environ): print('connected', sid) cpu_percent = psutil.cpu_percent(interval=1) virtual_memory = psutil.virtual_memory() memory_percent = virtual_memory.percent print('Initial CPU Usage:', cpu_percent) print('Initial Memory Usage:', memory_percent) data = { 'cpu_percent': cpu_percent, 'memory_percent': memory_percent } await sio.emit('usage', data)
@sio.event async def disconnect(sid): print('disconnected', sid)
async def monitor(): global running while running: cpu_percent = psutil.cpu_percent(interval=1) virtual_memory = psutil.virtual_memory() memory_percent = virtual_memory.percent data = { 'cpu_percent': cpu_percent, 'memory_percent': memory_percent } await sio.emit('usage', data) await sio.sleep(1)
@sio.on('start_monitor') async def start_monitor(sid): print('Starting System monitor...') global running running = True sio.start_background_task(monitor)
@sio.on('stop_monitor') async def stop_monitor(sid): print('Stopping System monitor...') global running running = False
@app.get("/aichat") async def aiChat(request: Request): return {"message": "Hello, AI Chat!"}
if __name__ == '__main__': uvicorn.run(app, host="0.0.0.0", port=8000)
|
前端连接代码:注意这里的路径是 /ws/socket.io
1
| socketRef.current = io("http://183.232.150.130:1080", {path:'/ws/socket.io', autoConnect: true})
|
参考:https://github.com/tiangolo/fastapi/issues/3666
1 2 3 4
| if app.mount('/ws') in server the client need sio.connect(url, socketio_path='/ws/docket.io')
So strange
|