C#基于SSE传递消息给Vue前端实现即时单向通讯

一、简述

        通常前端调用后端的API,调用到了,等待执行完,拿到返回的数据,进行渲染,流程就完事了。如果想要即时怎么办?如果你想问什么场景非要即时通讯,那可就很多了,比如在线聊天、实时数据推送、视频会议等等。

        本人这里是要实现的流程是,Vue调用C#的API,然后API内新线程调用python执行任务,然后API就给前端返回执行开始的消息,Vue和API就结束了。但是python执行的是十分耗时的任务,需要不断的把中间节点的消息输出到前端,是这样子一个场景。

        python把消息不能直接输出到前端,而是要返回给c#,这个通c#的Process接收消息,就可以获得到,然后就是c#如果把消息传递给前端的事情了,所以做了一下调研。

二、技术路线

        一共有三种技术路线。

1、websocket

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {@Overridepublic void configureMessageBroker(MessageBrokerRegistry config) {config.enableSimpleBroker("/topic");config.setApplicationDestinationPrefixes("/app");}@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/progress").withSockJS();}
}@Controller
public class ProgressController {@MessageMapping("/progress")@SendTo("/topic/progress")public ProgressMessage updateProgress(ProgressMessage progressMessage) {// 这里可以是更新进度的逻辑return progressMessage;}
}public class ProgressMessage {private int progress;// 省略构造函数、getter和setter
}

        vue参考代码

<template><div><progress :value="progressValue" max="100"></progress></div>
</template><script>
export default {data() {return {progressValue: 0,socket: null};},created() {this.socket = new SockJS('/progress');let stompClient = Stomp.over(this.socket);stompClient.connect({}, frame => {stompClient.subscribe('/topic/progress', progressData => {let progress = JSON.parse(progressData.body).progress;this.progressValue = progress;});});},beforeDestroy() {this.socket.close();}
};
</script>

2、长轮询

        长轮询就特别简单,前端搞个定时器,不断的调用接口,这种方法适合不那么即时的,否则量大了,就是麻烦事。

@RestController
public class TaskController {@GetMapping("/task/progress/{taskId}")public int getProgress(@PathVariable String taskId) {// 查询任务进度int progress = taskService.getProgress(taskId);return progress;}
}

        vue参考代码

export default {data() {return {progress: 0,taskId: '123' // 替换为实际任务ID};},mounted() {this.getProgress();},methods: {getProgress() {this.$http.get(`/task/progress/${this.taskId}`).then(response => {this.progress = response.data;// 继续轮询setTimeout(this.getProgress, 1000); });}}
}

3、Server-Sent Events(SSE)

        SSE 维护一个开放的 HTTP/1.1 连接,SSE请求将保持打开状态,直到客户端或服务器决定结束它,并且只是将新信息简单地写入缓冲区。

        C#API参考代码。

[HttpGet("{id}")]
public async Task PushMessage(int id)
{Response.Headers["Content-Type"] = "text/event-stream";Response.Headers["Cache-Control"] = "no-cache";Response.Headers["Connection"] = "keep-alive";Response.Headers["Access-Control-Allow-Origin"] = "*"; // 允许跨域try{await Response.WriteAsync($"data: 服务器已经连接\r\r");await Response.Body.FlushAsync();await Task.Delay(1000);}catch (Exception ex){System.Console.WriteLine("异常:"+ex.ToString());}finally{System.Console.WriteLine("客户端断开");}
}

        vue参考代码

mounted() {//后面跟的this.data.fid,是我需要的,如果不需要可以去掉,并修改c#的接口this.source = new EventSource('http://你的接口地址/PushMessage/' + this.data.fid);this.source.onmessage = (event) => {if (event.data === '服务器已经连接'){this.connection = false}else{this.pythonLog += '<br/>'this.pythonLog += event.data}// const data = JSON.parse(event.data);// console.log(event.data)// this.events.push({ id: Date.now(), data: data });}this.source.onerror = (error) => {console.error('SSE error:', error)}},

三、总结

1、小结

        上面的websocket的代码是从别人哪里直接copy来的,没有进行测试。长轮询的代码也没有什么值得参考的。但是最后的SSE的代码片段是经过验证的,只不过C#端的API里面精简了。

        总结来说,SSE更简单轻量,如果不需要维护太多状态,实时性还强,也不需要双向通讯,是比较好的选择。

        如果需要双向通讯,必然是websocket。

        如果是可以不那么频繁隔一段时间请求看看,成功失败都行的,长轮询就比较适合了。

2、注意事项 

大多数 Web 服务器都配置了请求超时。例如,Nginx默认proxy_read_timeout为60 秒。

另外根据服务器的不同,您可能需要配置各种缓存和缓冲机制。

不能无限制的使用,早期的浏览器的每个域的活动连接数限制为6个,现在的浏览器有所增加,但也不是无限制的。如果超出此限制,请求都将被停止,就会卡住(没有这方面的经验,ibm的网站说的)。另外csdn伤别人的说法是升级为HTTP2.0,需要域名和证书。

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

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

相关文章

Java 笔记 01:Java 概述,MarkDown 常用语法整理

一、前言 记录时间 [2024-04-18] 昨天整理完 Docker 基础后略微思索了一下&#xff0c;还是决定把 Java 捡起来&#xff0c;系统地学习一遍&#xff0c;参考的学习课程是狂神说 Java 零基础&#xff0c;真诚感激此系列视频对笔者的帮助。 零基础可以学 Java 吗&#xff1f;只要…

JVS低代码平台表单引擎:字符串拼接与逻辑函数的完美结合

字符串拼接使用逻辑函数配置 示例场景&#xff1a;通过按钮触发逻辑使用函数将两个日期字段组合为范围时间类型。 选择开始日期和结束日期后&#xff0c;点击【合并】按钮自动处理回显至起止日期字段。在【合并】按钮上设置逻辑。 注意&#xff1a;这里【起止日期】组件是数组…

【web开发02】后端开发Maven

后端开发Maven 1 Maven是什么&#xff1f;1.1 Maven基础概念1.1.2 仓库1.1.3 坐标 2 配置maven环境3 创建maven项目4 导入maven项目4 依赖管理4.1 依赖配置4.2 依赖传递4.2.1 排除依赖 4.3 依赖范围4.4 生命周期4.4.1 运行生命周期 1 Maven是什么&#xff1f; Maven本质是项目…

二次元AI绘画生成器免费:教你生成精美图片

二次元AI绘画生成器&#xff0c;无疑是现代技术与艺术完美结合的典范。这些工具不仅将复杂的绘画过程简化&#xff0c;更让每一个艺术爱好者的创意得以充分展现。这些生成器能够精准捕捉大家的创意精髓&#xff0c;将其转化为细腻、独特的二次元画作。无论是角色设计、场景描绘…

SpringMVC(五)【拦截器】

前言 今天来把 SpringMVC 最后一部分学完&#xff0c;虽然课时很短&#xff0c;但是学起来还是很慢的&#xff0c;不过确收获很大。不得不感慨学大数据确实有必要把 SSM、SpringBoot 等各种 JavaEE 技术好好学一学&#xff0c;收获很大&#xff0c;尽管我们到现在 Java 代码写了…

Redis几种常见的应用方式

1.登录认证 redis最常见的应用就是&#xff0c;登录认证把。再首次登录返回给前端token&#xff0c;把用户名和登录状态缓存到redis一段时间&#xff0c;每次其他请求进来过滤器那这token解析出来的用户名或其他关键的key值&#xff0c;再redis里面查询缓存&#xff0c;有则直…

【算法】二分查找

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、二分查找二、查找元素的第一个和最后一个位置三、x的平方根四、搜索插入位置五、山脉数组的峰顶索引…

【Leetcode每日一题】 分治 - 排序数组(难度⭐⭐)(60)

1. 题目解析 题目链接&#xff1a;912. 排序数组 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 算法思路&#xff1a; 快速排序作为一种经典的排序算法&#xff0c;其核心思想在于通过“分而治之”的策略&#xff…

eCongnition 根据栅格类别图分类分割结果

目录 1、导入标签文件 2、根据栅格类别计算对象类别 3、导出栅格计算的类别 1、导入标签文件 导入栅格类别文件Label.tif 参考&#xff1a;eCongnition 对图像进行多尺度分割-CSDN博客 2、根据栅格类别计算对象类别 对类别栅格创建 mode[Maximum] 特征&#xff0c;该特征…

SQL Serve---嵌套查询

定义 嵌套查询&#xff1a;主要用于复杂的查询中。在SQL语言中&#xff0c;一个Select From Where语句称为一个查询块&#xff0c;将一个查询块嵌套在另一个查询的Where子句或Having短语中的查询称为嵌套查询。 子查询的类型 使用别名的子查询 使用IN和NOT IN的子查询 使用比较…

基于SSM的列车订票管理系统(含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的列车订票管理系统3拥有两种角色&#xff1b;管理员、用户 管理员&#xff1a;用户管理、车票管理、购票指南管理、系统管理等 用户&#xff1a;发布帖子、登录注册、购票等 1.…

数据结构速成--串

由于是速成专题&#xff0c;因此内容不会十分全面&#xff0c;只会涵盖考试重点&#xff0c;各学校课程要求不同 &#xff0c;大家可以按照考纲复习&#xff0c;不全面的内容&#xff0c;可以看一下小编主页数据结构初阶的内容&#xff0c;找到对应专题详细学习一下。 目录 …

【Linux冯诺依曼体系结构】

目录 1.冯诺依曼体系结构原理 1.冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体系。 截至目前&#xff0c;我们所认识的计算机&#xff0c;都是有一个个的硬件组件组成 输入单元&#…

最新SpringBoot项目财务管理系统

采用技术 最新SpringBoot项目财务管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 系统登录页面 管理员功能 管理员功能页面 员工管理页面 部…

SpringBoot多数据源(五)

SpringBoot多数据源-集成多个mybatis框架 1.基本框架2.使用2.1项目结构2.2 依赖导入2.3 application.yml配置2.4 创建读与写的SqlSessionFactoryBean 3.总结 1.基本框架 通过启动多个SqlSessionFactoryBean&#xff0c;每个SqlSessionFactoryBean对应一个datasource和指定位置的…

STM32G431RBT6移植FreeRTOS

引言&#xff1a; 本文专门为参加了蓝桥杯嵌入式赛道的同学准备&#xff0c; 大家可能会有这样一个问题&#xff0c; 比完赛之后&#xff0c; 对于像继续使用STM32G431RBT6学习FreeRTOS的&#xff0c; 发现网上的教程使用的板子基本上都是F1和F4的&#xff0c; 其实呢&#xff…

二叉树的最大深度 - LeetCode 热题 37

大家好&#xff01;我是曾续缘&#x1f61b; 今天是《LeetCode 热题 100》系列 发车第 37 天 二叉树第 2 题 ❤️点赞 &#x1f44d; 收藏 ⭐再看&#xff0c;养成习惯 二叉树的最大深度 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最…

JAVA面向对象(下 )(一、继承和方法重写)

一、继承 1.1 什么是继承 生活中继承是指&#xff1a; 继承财产>延续财产 继承/遗传 父母的长相&#xff0c;基因 > 延续上一代的基因 继承技能、专业、职位 >延续 继承中华民族的传统文化 > 延续 青出于蓝而胜于蓝 或 长江后浪推前浪&#xff0c;前浪被拍在…

【图像分割】光流生成标签(matlab)

文章目录 1. 框架2. opticalFlow_label3. 光流 1. 框架 2. opticalFlow_label close all; clear; clc; % 使用光流进行标签的生成 %% 视频帧的读取 npy_data readNPY(train.npy);%% 提取标签的坐标 first_label squeeze(npy_data(2,1,:,:)); h fspecial("gaussian&quo…

PgSQL之WITH Queries/Statement

PostgreSQL WITH 子句 在 PostgreSQL 中&#xff0c;WITH 子句提供了一种编写辅助语句的方法&#xff0c;以便在更大的查询中使用。 WITH 子句有助于将复杂的大型查询分解为更简单的表单&#xff0c;便于阅读。这些语句通常称为通用表表达式&#xff08;Common Table Express…