流式输出方案:sse与websocket的使用

1、sse(Server-Sent Events)

SSE是一种允许服务器向浏览器推送实时更新的技术。它基于HTTP协议,是一种单向的通信方式

  • 单向通信
  • 基于HTTP
  • 自动重连(内置了自动重连机制,当连接断开时,浏览器会自动尝试重新连接)
    在这里插入图片描述
1.1 简易版:vue+python

vue:

<template><div class="container"><div id="app"><h1>SSE Stream Output</h1><div v-for="message in messages" :key="message">{{ message }}</div></div><el-button @click="sendMsg">send message</el-button></div>
</template><script setup lang="ts">import { ref } from 'vue';const messages = ref<any>([]);const sendMsg = () => {const eventSource = new EventSource('http://localhost:5000/stream');eventSource.onmessage = event => {messages.value.push(event.data);};};
</script><style scoped></style>

python:

from flask import Flask, Response
from flask_cors import CORS
import timeapp = Flask(__name__)
CORS(app)
def generate_stream():while True:time.sleep(1)yield f"data: 当前时间: {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n"@app.route('/stream',methods=['GET', 'POST'])
def stream():data = request.jsonfile = data.get('file')print(file)return Response(generate_stream(), mimetype='text/event-stream')if __name__ == '__main__':app.run(debug=True)
1.2 post请求版本:vue(@microsoft/fetch-event-source)+python

安装:npm install @microsoft/fetch-event-source

<template><div class="container"><div id="app"><h1>SSE Stream Output</h1><div v-for="message in messages" :key="message">{{ message }}</div></div><el-button @click="sendMsg">send message</el-button></div><el-button @click="stop">stop</el-button>
</template><script setup lang="ts">import { ref } from 'vue';import { fetchEventSource } from '@microsoft/fetch-event-source';const messages = ref<any>([]);const sendMsg = () => {// const eventSource = new EventSource('http://localhost:5000/stream');// eventSource.onmessage = event => {// 	messages.value.push(event.data);// };connectToEventStream();};let controller: any = null;function connectToEventStream() {if (controller) {controller.abort();controller = null;}//没有的话就到这一步controller = new AbortController();let eventSource: any = fetchEventSource(`http://localhost:5000/stream`, {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({file: 'testFile',userId: '1234',}),signal: controller.signal,openWhenHidden: true,onmessage(event: any) {console.log(event, 'event');messages.value.push(event.data);},onerror() {controller.abort();eventSource.close();},});}// 停止function stop() {if (controller) {controller.abort();controller = null;}}
</script><style scoped></style>

2.websocket

WebSocket 是一种网络通信协议,它允许在客户端(如浏览器)和服务器之间建立全双工(双向)的持久连接。
特点:

  • 全双工通信:客户端和服务器可以同时发送和接收数据。
  • 持久连接:连接建立后,客户端和服务器可以保持长时间的通信,而不需要频繁地重新建立连接。
  • 低延迟:数据可以实时传输,适合实时聊天、在线游戏、股票行情等场景。
  • 基于 TCP:WebSocket 是基于 TCP 协议的,确保数据的可靠传输。
  • 轻量级:相比 HTTP,WebSocket 的协议头更小,减少了通信开销。

websocket.js

export default class WebSocketClient {constructor(url, options = {}) {this.url = url; // WebSocket 服务器地址this.options = {maxReconnectAttempts: 5, // 最大重连次数reconnectInterval: 5000, // 重连间隔(毫秒)heartbeatInterval: 30000, // 心跳间隔(毫秒)...options, // 允许自定义配置};this.socket = null; // WebSocket 实例this.reconnectAttempts = 0; // 当前重连次数this.heartbeatTimer = null; // 心跳定时器this.messageListeners = []; // 消息监听器this.openListeners = []; // 连接成功监听器this.closeListeners = []; // 连接关闭监听器this.errorListeners = []; // 错误监听器this.init();}// 初始化 WebSocketinit() {this.socket = new WebSocket(this.url);// 监听连接成功this.socket.onopen = () => {console.log("WebSocket 连接成功");this.reconnectAttempts = 0; // 重置重连次数this.startHeartbeat(); // 启动心跳检测this.emitOpen(); // 触发连接成功事件};// 监听服务器消息this.socket.onmessage = (event) => {const data = event.data;console.log("收到服务器消息:", data);this.emitMessage(data); // 触发消息事件// 如果是心跳响应,则重置心跳检测if (data === "pong") {this.resetHeartbeat();}};// 监听连接关闭this.socket.onclose = () => {console.log("WebSocket 连接已关闭");this.stopHeartbeat(); // 停止心跳检测this.emitClose(); // 触发连接关闭事件this.handleReconnect(); // 尝试重连};// 监听连接错误this.socket.onerror = (error) => {console.error("WebSocket 错误:", error);this.stopHeartbeat(); // 停止心跳检测this.emitError(error); // 触发错误事件this.handleReconnect(); // 尝试重连};}// 启动心跳检测startHeartbeat() {this.heartbeatTimer = setInterval(() => {if (this.socket && this.socket.readyState === WebSocket.OPEN) {this.socket.send("ping"); // 发送心跳消息console.log("发送心跳: ping");}}, this.options.heartbeatInterval);}// 重置心跳检测resetHeartbeat() {this.stopHeartbeat();this.startHeartbeat();}// 停止心跳检测stopHeartbeat() {if (this.heartbeatTimer) {clearInterval(this.heartbeatTimer);this.heartbeatTimer = null;}}// 处理重连handleReconnect() {if (this.reconnectAttempts < this.options.maxReconnectAttempts) {this.reconnectAttempts++;console.log(`尝试重连,第 ${this.reconnectAttempts}`);setTimeout(() => {this.init(); // 重新初始化 WebSocket}, this.options.reconnectInterval);} else {console.error("已达到最大重连次数,停止重连");}}// 发送消息send(message) {if (this.socket && this.socket.readyState === WebSocket.OPEN) {this.socket.send(JSON.stringify(message));} else {console.error("WebSocket 未连接,无法发送消息");}}// 关闭连接close() {if (this.socket) {this.socket.close();}this.stopHeartbeat();}// 添加消息监听器onMessage(listener) {this.messageListeners.push(listener);}// 添加连接成功监听器onOpen(listener) {this.openListeners.push(listener);}// 添加连接关闭监听器onClose(listener) {this.closeListeners.push(listener);}// 添加错误监听器onError(listener) {this.errorListeners.push(listener);}// 触发消息事件emitMessage(data) {this.messageListeners.forEach((listener) => listener(data));}// 触发连接成功事件emitOpen() {this.openListeners.forEach((listener) => listener());}// 触发连接关闭事件emitClose() {this.closeListeners.forEach((listener) => listener());}// 触发错误事件emitError(error) {this.errorListeners.forEach((listener) => listener(error));}
}

websocket.vue

<template><div class="container"><div><h1>Stream Output</h1><ul><li v-for="(message, index) in messages" :key="index">{{ message }}</li></ul></div><el-input v-model="inputVal"></el-input><el-button @click="sendMsg">send message</el-button></div>
</template><script setup>import { ref, onMounted } from 'vue';import WebSocketClient from './websocket';const messages = ref([]);const inputVal = ref('');const sendMsg = () => {const wsClient = new WebSocketClient('ws://localhost:8000/ws', {maxReconnectAttempts: 3, // 自定义最大重连次数reconnectInterval: 3000, // 自定义重连间隔heartbeatInterval: 20000, // 自定义心跳间隔});wsClient.onOpen(() => {console.log('WebSocket 连接成功');wsClient.send({input:inputVal.value,info:'消息'})});wsClient.onMessage(data => {console.log('收到消息:', data);messages.value.push(data)});};
</script>

python

from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse
import asyncio
app = FastAPI()# WebSocket 路由
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):await websocket.accept()  # 接受客户端连接try:while True:# 接收客户端消息data = await websocket.receive_text()print(f"收到客户端消息: {data}")# 模拟流式响应for i in range(5):response = f"服务器响应: {data} - {i + 1}"await websocket.send_text(response)  # 发送消息给客户端await asyncio.sleep(1)  # 模拟延迟except Exception as e:print(f"WebSocket 连接异常: {e}")finally:await websocket.close()  # 关闭连接# 启动服务
if __name__ == "__main__":import uvicornuvicorn.run(app, host="0.0.0.0", port=8000)

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

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

相关文章

基于定制开发开源AI大模型S2B2C商城小程序的商品选品策略研究

摘要&#xff1a;随着电子商务的蓬勃发展和技术的不断进步&#xff0c;商品选品在电商领域中的重要性日益凸显。特别是在定制开发开源AI大模型S2B2C商城小程序的环境下&#xff0c;如何精准、高效地选择推广商品&#xff0c;成为商家面临的一大挑战。本文首先分析了商品选品的基…

时序论文41 | Medformer:基于多粒度patch的时序分类模型

论文标题&#xff1a;Medformer: A Multi-Granularity Patching Transformer for Medical Time-Series Classification 论文链接&#xff1a;https://arxiv.org/abs/2405.19363 代码链接&#xff1a;https://github.com/DL4mHealth/Medformer. &#xff08;后台回复“交流”…

建筑兔零基础自学python记录32|学过的函数代码记录19-25

这是之前matplotlib用过的代码记录&#xff0c;以防忘记记录一下: 19.price_data 是一个 NumPy 记录股票数组。每一列可以有不同的数据类型&#xff0c;并且每列都有一个对应的字段名。&#xff08;类似excel的表中的列&#xff09; date&#xff1a;存储交易日期&#xff0c…

面试八股文--数据库基础知识总结(2) MySQL

本文介绍关于MySQL的相关面试知识 一、关系型数据库 1、定义 关系型数据库&#xff08;Relational Database&#xff09;是一种基于关系模型的数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;它将数据存储在表格&#xff08;表&#xff09;中&#xff0c;并通过表格…

Linux:目录创建命令mkdir功能及用法详解

mkdir是Make Directory的缩写&#xff0c;该命令在 Linux 中用于创建目录&#xff08;单层或多层&#xff09;&#xff0c;在Linux中很常用&#xff0c;可以说是基础性命令。该命令支持&#xff1a;1&#xff09;创建单层或多层目录2&#xff09;直接指定目录权限。本文详细介绍…

2024年国赛高教杯数学建模D题反潜航空深弹命中概率问题解题全过程文档及程序

2024年国赛高教杯数学建模 D题 反潜航空深弹命中概率问题 原题再现 应用深水炸弹&#xff08;简称深弹&#xff09;反潜&#xff0c;曾是二战时期反潜的重要手段&#xff0c;而随着现代军事技术的发展&#xff0c;鱼雷已成为现代反潜作战的主要武器。但是&#xff0c;在海峡或…

Visual Studio Code 远程开发方法

方法1 共享屏幕远程控制&#xff0c;如 to desk, 向日葵 &#xff0c;像素太差&#xff0c;放弃 方法2 内网穿透 ssh 第二个方法又很麻烦&#xff0c;尤其是对于 windows 电脑&#xff0c;要使用 ssh 还需要额外安装杂七杂八的东西&#xff1b;并且内网穿透服务提供商提供的…

SQLite 安装教程以及可视化工具介绍

目录 简述 1. Windows 系统安装 1.1 下载预编译的二进制文件 1.2 解压文件 1.3 配置环境变量 1.4 验证安装 2. GUI 可视化工具 2.1 免费工具 2.1.1 DB Browser for SQLite 2.1.2 SQLiteStudio 2.1.3 SQLite Expert 2.1.4 SQLiteGUI 2.1.5 Antares SQL 2.1.6 DbGa…

smolagents学习笔记系列(五)Tools-in-depth-guide

这篇文章锁定官网教程中的 Tools-in-depth-guide 章节&#xff0c;主要介绍了如何详细构造自己的Tools&#xff0c;在之前的博文 smolagents学习笔记系列&#xff08;二&#xff09;Agents - Guided tour 中我初步介绍了下如何将一个函数或一个类声明成 smolagents 的工具&…

LLM2CLIP论文学习笔记:强大的语言模型解锁更丰富的视觉表征

1. 写在前面 今天分享的一篇论文《LLM2CLIP: P OWERFUL L ANGUAGE M ODEL U NLOCKS R ICHER V ISUAL R EPRESENTATION》&#xff0c; 2024年9月微软和同济大学的一篇paper&#xff0c; 是多模态领域的一篇工作&#xff0c;主要探索了如何将大模型融合到Clip模型里面来进一步提…

一键部署DeepSeek

腾讯Cloud Studio提供DeepSeek一键部署功能&#xff0c;0行代码&#xff0c;秒级部署使用&#xff01; 重点是每月免费提供10000分钟&#xff01; 不用等待模型下载&#xff0c;创建即可使用。 内置 Ollama、DeepSeek-R1 1.5B、7B、8B、14B 及 32B 模型。 热门模板 AI模板 前…

【计算机网络】IP协议

目录 1. 协议头格式 2. 网段划分 3. 特殊的IP 4. 公网IP && 内网IP 总结 网络层的IP协议主要解决的是什么问题&#xff1f;——将数据包从B主机发送给C主机&#xff1b;传输层协议tcp提供可靠的策略&#xff1b;网络层IP协议提供数据数据传输的能力&#xff1b; 发…

YOLOv12 ——基于卷积神经网络的快速推理速度与注意力机制带来的增强性能结合

概述 实时目标检测对于许多实际应用来说已经变得至关重要&#xff0c;而Ultralytics公司开发的YOLO&#xff08;You Only Look Once&#xff0c;只看一次&#xff09;系列一直是最先进的模型系列&#xff0c;在速度和准确性之间提供了稳健的平衡。注意力机制的低效阻碍了它们在…

2022年全国职业院校技能大赛网络系统管理赛项模块A:网络构建(样题6)-网络部分解析-附详细代码

目录 附录1:拓扑图 附录2:地址规划表 1.SW1 2.SW2 3.SW3 4.SW4 5.VSU 6.SW7 7.R1 8.R2 9.R3 10.AC1 11.AC2 12.EG1 13.EG2 附录1:拓扑图 附录2:地址规划表

C#实现本地Deepseek模型及其他模型的对话

前言 1、C#实现本地AI聊天功能 WPFOllamaSharpe实现本地聊天功能,可以选择使用Deepseek 及其他模型。 2、此程序默认你已经安装好了Ollama。 在运行前需要线安装好Ollama,如何安装请自行搜索 Ollama下载地址&#xff1a; https://ollama.org.cn Ollama模型下载地址&#xf…

突破“第一崇拜“:五维心理重构之路

一、视频介绍 在这个崇尚"第一"的时代&#xff0c;我们如何找到自己的独特价值&#xff1f;本视频将带您踏上五维心理重构之旅&#xff0c;从诗意人生的角度探讨如何突破"圣人之下皆蝼蚁"的局限。我们将穿越人生的不同阶段&#xff0c;从青春的意气风发到…

SpringWeb

目录 一.SpringWeb 1.SpringWeb 概述 2.SpringWEB 特点 3.SpringWeb 运行流程 4.SpringWEB 组件 二.搭建SpringWeb 1.在pom.xml中导包 2.配置DispatcherServlet 3.开启SpringWEB注解 4.测试 三.接收请求 1.定义地址、请求方式 2.获取请求数据 1&#xff09;使用r…

性能测试的方案编写与执行步骤

性能测试计划书 在测试过程中我们如果编写一份性能测试计划书&#xff0c;需要一下几个背景板块及要点 性能测试的流程&#xff1a; 确认需求&#xff08;确认正确的需求) —>编写测试方案&#xff08;准备怎么动手&#xff09;测试环节—>&#xff08;尽量与生成配置一…

[AI]从零开始的树莓派运行DeepSeek模型教程

一、前言 在前面的教程中&#xff0c;教了大家如何在windows中使用llama.cpp来运行DeepSeek模型。根据前面的教程中&#xff0c;我们也了解到了&#xff0c;我们只需要编译好llama.cpp就可以运行DeepSeek以及类似的LLM模型。那么本次教程就来教大家如何使用树莓派来运行大模型。…

03_pyqt5 + vlc 实现视频播放器

1.功能需求如图 按钮: 播放/暂停, 前进/后退, 视频上一个/下一个, 打开视频进度条: 视频进度条显示, 进度条拖拽, 音量控制按键控制: 1,2,3,4缩放画面大小, 2.方案选择 开发语言: python UI界面: pyqt5 qt_designed 设计ui布局 视频编码: python-vlc 方案说明: 视频解码可…