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

FastAPI: websocket的用法及举例

1. Websocket

1.1 Websocket介绍

  WebSocket 是一种在单个TCP连接上进行全双工通信的协议,允许客户端和服务器之间相互发送数据,而不需要像传统的HTTP请求-响应模型那样频繁建立和断开连接。
全双工通信(Full-Duplex Communication)是一种通信模式,允许通信双方同时发送和接收数据。换句话说,数据可以同时从两端双向传输,而不会相互阻塞或干扰。

1.2 FastAPI中的Websocket

  FastAPI提供了对WebSocket的原生支持,允许你轻松构建高效的实时应用,如聊天室、实时数据更新等。

1.2.1 装饰器

  FastAPI中与WebSocket相关的主要装饰器为 @app.websocket。该装饰器的作用和参数如下:

  • 作用:将一个路径(如/ws)与一个处理WebSocket请求的函数关联。当客户端通过WebSocket连接该路径时,FastAPI会调用该函数处理连接和通信。
  • 参数:它接受的参数与其他路由装饰器相同,主要是路径(URL),可选地也能设置依赖项、权限等。

代码举例如下(当客户端通过WebSocket连接/ws路径时,FastAPI将执行下面的websocket_endpoint函数):

from fastapi import FastAPI, WebSocket
app = FastAPI()
# 定义一个 WebSocket 路由
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):await websocket.accept()  # 接受 WebSocket 连接while True:data = await websocket.receive_text()  # 接收来自客户端的消息await websocket.send_text(f"Message text was: {data}")  # 回复消息给客户端
1.2.2 websocket相关方法

  FastAPI提供了处理WebSocket各种事件的方法,包括接受消息、发送消息、关闭连接等。具体如下:

  • websocket.accept:接受WebSocket连接请求。
  • websocket.receive_text:接收客户端发来的文本消息。
  • websocket.send_text:向客户端发送文本消息。
  • websocket.close:关闭WebSocket连接。

2. 构建对话机器人

  这里我们用FastAPI和React构建一个聊天机器人。这里关于机器人的后端处理逻辑这里不做详细介绍(这里不介绍CSS代码)。具体代码如下:
React中App.tsx代码如下:

import './App.css';
import ChatPage from './components/ChatPage';function App() {return (<div className="App"><div className="header"><div className="header-logo"><img src="https://cdn.builder.io/api/v1/image/assets/TEMP/b0db057162d379f22892cd5ae4d13c509717e0a81da39be3f65cb94e15556ed7?apiKey=0682bce60b3549f085131079f1bf89f0&&apiKey=0682bce60b3549f085131079f1bf89f0" alt="Chainlit" /> <div className="header-title">SmartRecommend服务推荐助手</div></div></div><div className='body-container'><div className="main"><div className='chatpage'><ChatPage /></div></div></div></div>);
}
export default App;

React中ChatPage.tsx代码如下:

import "./ChatPage.css";
import { useEffect, useState} from "react";
import { nanoid } from 'nanoid';interface Message{id:string,name:string,type:string,output:string,createdAt:number|string,
}
function ChatPage() {const [inputValue, setInputValue] = useState("");const [messages,setMessages] = useState<Message[]>([]);const [socket,setSocket] = useState<WebSocket|null>(null);useEffect(() => {const ws = new WebSocket("ws://localhost:8000/ws/chat");ws.onopen = () => {console.log("websocket链接已建立!");};ws.onmessage = (event) => {const message = JSON.parse(event.data);setMessages((prevMessages) => [...prevMessages, message]);};ws.onerror = (error) => {console.log('WebSocket错误:', error);};ws.onclose=()=>{console.log("websocket链接已关闭!");}setSocket(ws);return () => {ws.close();}},[]);const handleSendMessage = () => {const content = inputValue.trim();if (content) {const message: Message={id: nanoid(),name: "User",type: "user_message",output: content,createdAt: Date.now(),};setMessages((prevMessages) => [...prevMessages, message]);socket?.send(JSON.stringify(message));}setInputValue("");};const renderMessage = (message:Message,index:number) => {const dateOptions: Intl.DateTimeFormatOptions = {hour: "2-digit",minute: "2-digit",};const date = new Date(message.createdAt).toLocaleTimeString(undefined,dateOptions);if(message.type === "user_message") {return (<div key={message.id} className="chat-box-user"><div className="user-avatar">U</div><div className="bot-user-content"><div className="user-icon"><div className="bot-user-name">{message.name}</div><div className="bot-user-time">{date}</div></div><div className="user-chat-message">{message.output}</div></div></div>);} else {return (<div key={message.id} className="chat-box-bot"><div className="bot-avatar">B</div><div className="bot-user-content"><div className="bot-icon"><div className="bot-user-name">{message.name}</div><div className="bot-user-time">{date}</div></div><div className="bot-chat-message">{message.output}</div></div></div>);};};return (<div className="chat-container"><div className="chat-box">{messages.map(renderMessage)}</div><div className="fixed-bottom"><input className="fixed-bottom-input" type="text"value={inputValue}placeholder="你可以输入“金仔金仔”唤醒服务"onChange={(e) => setInputValue(e.target.value)}onKeyUp={(e) => {if (e.key === "Enter") {handleSendMessage();}}}></input><button onClick={handleSendMessage} className="button" type="submit">Send</button></div></div>); 
}
export default ChatPage;

后端FastAPI代码:

from fastapi import FastAPI, WebSocket,HTTPException
import uvicorn
from fastapi.middleware.cors import CORSMiddleware
from typing import List
import json
import datetime
from nanoid import generate
import httpxapp=FastAPI()
app.add_middleware(CORSMiddleware,allow_origins=["http://localhost:3000"],allow_credentials=True,allow_methods=["*"],allow_headers=["*"],
)
clients: List[WebSocket] = []RASA_API_URL="http://localhost:5005/webhooks/rest/webhook"@app.websocket("/ws/chat")
async def websocket_endpoint(websocket: WebSocket):await websocket.accept()clients.append(websocket)try:while True:data = await websocket.receive_text()for client in clients:text={"id": generate(),"name":"Bot","type":"bot_message","output":json.loads(data)["output"],"createdAt":int(datetime.datetime.now().timestamp()*1000)}text=json.dumps(text)await client.send_text(text)except Exception as e:print(e)clients.remove(websocket)if __name__ == "__main__":uvicorn.run(app, host="0.0.0.0", port=8000)

相关文章:

FastAPI: websocket的用法及举例

1. Websocket 1.1 Websocket介绍 WebSocket 是一种在单个TCP连接上进行全双工通信的协议&#xff0c;允许客户端和服务器之间相互发送数据&#xff0c;而不需要像传统的HTTP请求-响应模型那样频繁建立和断开连接。 全双工通信(Full-Duplex Communication)是一种通信模式&#…...

JavaSE——面向对象2:方法的调用机制、传参机制、方法递归、方法重载、可变参数、作用域

目录 一、成员方法 (一)方法的快速入门 (二)方法的调用机制(重要) (三)方法的定义 (四)注意事项和使用细节 1.访问修饰符(作用是控制方法的使用范围) 2.返回的数据类型 3.方法名 4.形参列表 5.方法体 6.方法调用细节说明 (五)传参机制 1.基本数据类型的传参机制 …...

Vue+Flask

App.vue 首先要安装 npm install axios<template><div><h1>{{ message }}</h1><input v-model"name" placeholder"Enter your name" /><input v-model"age" placeholder"Enter your age" /><…...

深入剖析 Android Lifecycle:构建高效稳定的应用

在 Android 开发中&#xff0c;管理应用组件的生命周期是至关重要的。正确处理生命周期事件可以确保应用的性能、稳定性和用户体验。Android Framework 提供了一系列的机制来管理应用组件的生命周期&#xff0c;而android.arch.lifecycle库则为我们提供了更简洁、更灵活的方式来…...

ElasticSearch分词器、相关性详解与聚合查询实战

目录 1. ES分词器详解 1.1 基本概念 1.2 分词发生时期 1.3 分词器的组成 切词器&#xff1a;Tokenizer 词项过滤器&#xff1a;Token Filter 字符过滤器&#xff1a;Character Filter 1.4 倒排索引的数据结构 2. 相关性详解 2.1 什么是相关性&#xff08;Relevance&am…...

删除二叉树中以x为根节点的子树(包括根结点)

已知二叉树以二叉链表存储&#xff0c;编写算法完成&#xff1a;对于树中每个元素值为x的结点&#xff0c;删除以它为根的子树&#xff0c;并释放相应的空间。 思想&#xff1a; 删除二叉树采用后序遍历。先删除左子树&#xff0c;然后右子树&#xff0c;最后根。 利用层次遍…...

Netty 与 WebSocket之间的关系

WebSocketProtocolHandler 和 Netty 在处理 WebSocket 连接时扮演不同的角色&#xff0c;但它们通常是一起使用的&#xff0c;尤其是在基于 Netty 的项目中。为了更好地理解它们之间的区别&#xff0c;我们首先需要了解 WebSocket 和 Netty 的基本概念。 WebSocket WebSocket…...

通信工程学习:什么是CSMA/CA载波监听多路访问/冲突避免

CSMA/CA&#xff1a;载波监听多路访问/冲突避免 CSMA/CA&#xff08;Carrier Sense Multiple Access/Collision Avoidance&#xff09;&#xff0c;即载波监听多路访问/冲突避免&#xff0c;是一种用于数据传输时避免各站点之间冲突的算法&#xff0c;尤其适用于无线局域网&…...

JAVA并发编程系列(13)Future、FutureTask异步小王子

美团本地生活面试&#xff1a;模拟外卖订单处理&#xff0c;客户支付提交订单后&#xff0c;查询订单详情&#xff0c;后台需要查询店铺备餐进度、以及外卖员目前位置信息后再返回。 时间好快&#xff0c;一转眼不到一个月时间&#xff0c;已经完成分享synchronized、volatile、…...

【python爬虫可以获取到谷歌影像吗?】如何有效下载谷歌影像?

【python爬虫可以获取到谷歌影像吗&#xff1f;】如何有效下载谷歌影像&#xff1f; 【python爬虫可以获取到谷歌影像吗&#xff1f;】如何有效下载谷歌影像&#xff1f; 文章目录 【python爬虫可以获取到谷歌影像吗&#xff1f;】如何有效下载谷歌影像&#xff1f;前言1. 使用…...

Windows 上安装 PostgreSQL

Windows 上安装 PostgreSQL PostgreSQL 是一款功能强大的开源关系数据库管理系统,广泛用于各种应用场景。在 Windows 系统上安装 PostgreSQL 相对简单,但需要遵循一系列步骤。本文将详细介绍在 Windows 上安装 PostgreSQL 的过程,并提供一些关键的配置和优化建议。 一、下…...

Vue 技术进阶 day2 数据监视的原理、其他内置指令、自定义指令、生命周期、组件化、VueComponent构造函数

目录 1.Vue监测数据的原理 1.1 原理 1.1.1 数据劫持 1.1.2 观察者模式(Vue内部的实现) 1.1.3 更新组件 1.1.4 计算属性和侦听器 1.2 后添加属性做响应式&#xff08;Vue.set / vm.$set&#xff09; 1.3 对象和数组的响应式 1.4 数据监视案例 2.指令 2.1 内置指令 2.…...

vue.js 原生js app端实现图片旋转、放大、缩小、拖拽

效果图&#xff1a; 旋转 放大&#xff1a;手机上可以双指放大缩小 拖拽 代码实现&#xff1a; html <div id"home" class"" v-cloak><!-- 上面三个按钮 图片自己解决 --><div class"headImage" v-if"showBtn">&l…...

MyBatis的注入问题

对之前文章的补充&#xff1a;MyBatis中的#{}与${}注入问题----原文链接 前言&#xff1a; MyBatis是一个流行的Java持久层框架&#xff0c;用于将对象与数据库中的数据进行映射。然而&#xff0c;如果不当使用&#xff0c;MyBatis也可能受到诸如SQL注入这类的安全问题的影响。…...

基于springboot的评分评教管理系统

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的评分评教管理系统1拥有三种角色 管理员&#xff1a;评价管理、学生管理、评分指标管理、课程管理、教师管理、管理员管理等教师&#xff1a;课程管理、学生管理、个人信…...

C嘎嘎入门篇:类和对象(2)

前言&#xff1a; 上一篇小编讲了类和对象&#xff08;1&#xff09;&#xff0c;当然&#xff0c;在看这篇文章之前&#xff0c;读者朋友们一定要掌握好前面的基础内容&#xff0c;因为这篇和前面息息相关&#xff0c;废话不多说&#xff0c;下面小编就加快步伐&#xff0c;开…...

数据库 - Mongo数据库

目录 前言 一、MongoDB的特点 二、Mongo的核心概念 三、MongoDB的优劣势 四、使用场景 五、MongoDB与其他数据库的对比 六、如何安装MongoDB 七、数据库指令操作 &#xff08;一&#xff09;基本数据库操作 &#xff08;1&#xff09;连接 MongoDB &#xff08;2&am…...

工业控制过等保三级需要的网络安全设备及详细讲解

在工业控制系统&#xff08;ICS&#xff09;的安全性日益受到重视的背景下&#xff0c;网络安全等级保护&#xff08;过等保&#xff09;三级作为一种重要的安全标准&#xff0c;对保障工业控制系统的安全运行有着重要的意义。过等保三级主要针对那些对安全性要求较高的系统&am…...

Android开发高级篇:MVVM框架与数据双向绑定

在Android开发中&#xff0c;MVVM&#xff08;Model-View-ViewModel&#xff09;架构模式以其高效、简洁的特点&#xff0c;成为越来越多开发者的首选。MVVM不仅实现了界面&#xff08;UI&#xff09;与业务逻辑的分离&#xff0c;还通过数据双向绑定技术&#xff0c;极大地简化…...

智能招聘系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;企业管理&#xff0c;招聘信息管理&#xff0c;应聘信息管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;招聘信息&#xff0c;我的 开发系统&…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

sshd代码修改banner

sshd服务连接之后会收到字符串&#xff1a; SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢&#xff1f; 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头&#xff0c…...