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 {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }
 
    @Override
    public 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.mfbz.cn/a/556791.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

gpt能生成ppt吗

gpt能生成ppt吗 GPT是一个高度通用的工具&#xff0c;适用于多种场景和领域&#xff0c;制作ppt只是它强大功能的冰山一角&#xff0c;具体包括&#xff1a; 信息查询与解释&#xff1a; 提供科学、技术、历史、文化等领域的详细解释和背景信息。 解答疑问&#xff0c;帮助…

前端css中transition的使用

前端css中transition的使用 一、前言二、transition的4个属性三、例子1.源码12.源码1运行效果 四、结语五、定位日期 一、前言 CSS中的transition&#xff08;过渡&#xff09;&#xff0c;根据字面意思就可以理解成一种变化状态的过程。当我们有一个方形&#xff0c;我们想让…

Java在MySQL数据报错Data truncation: Data too long for column ‘**‘ at row 1 处理

问题 在Java SpringBoot MyBatis 框架的项目中&#xff0c;一切正常&#xff0c;不过在一个接口的参数字段传入过大的数据就会报此错误&#xff1a; 请求常:org.springframework.dao.DataIntegrityViolationException: Error updating database.Cause:com.mysql.cj.jdbc.excep…

漫画项目管理 | 遇到强势甲方的不合理项目需求,我该怎么办?

&#x1f937;‍♂️ 遇到甲方强烈要求不合理需求怎么办? &#x1f938;‍♂️看似离谱的功能客户却一定要加? &#x1f939;‍♂️时间紧任务重&#xff0c;甲方却“什么都想要“? &#x1f93e;‍♂️明明初稿很完美&#xff0c;却被要求改来改去?** &#x1f468;‍…

学习STM32第十六天

RTC实时时钟 一、简介 RTC是一个独立的BCD格式定时器&#xff0c;提供一个时钟日历&#xff0c;两个可编程报警中断&#xff0c;一个具有中断功能周期性可编程唤醒标志&#xff0c;RTC和时钟配置系统处于后备区域。 通过两个32位寄存器以BCD格式实现秒、分钟、小时&#xff08…

Qt日志使用

QsLog使用 这篇讲qt的日志还是比较好的&#xff0c;可以在自己的函数里面配置这个日志框架实现自己所需的功能。 我接触的项目里面&#xff0c;假如有个函数功能执行错误了&#xff0c;我希望可以快速定位到这个错误&#xff0c;这个时候就需要到了日志&#xff0c;我咨询了有经…

使用Python脚本检测服务器信息并定时发送至管理员邮箱

在日常的系统管理工作中&#xff0c;监测服务器的资源占用情况至关重要&#xff0c;我们需要及时获得通知以便采取相应措施。我新装了一台UbuntuServer服务器&#xff0c;写了一个可以定期收集服务器的CPU、内存、网络和磁盘信息&#xff0c;并通过邮件将这些信息发送给管理员的…

Seal^_^【送书活动第一期】——《Vue.js+Node.js全栈开发实战(第2版)》

Seal^_^【送书活动第一期】——《Vue.jsNode.js全栈开发实战&#xff08;第2版&#xff09;》 一、参与方式二、本期推荐图书2.1 前 言2.2 作者简介2.3 图书简介2.4 本书特色2.5 编辑推荐2.6 书籍目录 三、正版购买 一、参与方式 1、关注博主的账号。 2、点赞、收藏、评论博主的…

C++练级之路——类和对象(下)

目录 1、构造函数初始化列表 2、类型转换 3、explicit关键字 4、static成员 5、友元 友元函数 友元类 6、内部类 7、匿名对象 8、拷贝构造时的一些编译器优化 差不多结束了&#xff0c;类和对象&#xff01; 1、构造函数初始化列表 初始化列表&#xff1a;以一个冒号…

了解MySQL的复制

了解MySQL的复制 MySQL的复制允许数据从一个MySQL数据库服务器&#xff08;主服务器&#xff09;复制到一个或多个MySQL数据库服务器&#xff08;从服务器&#xff09;。复制在数据库的扩展性和数据备份方面扮演着重要角色&#xff0c;特别是在大型企业和高可用性的应用场景中…

时序预测 | Transformer时间序列预测 Matlab代码

文章目录 效果一览文章概述源码设计参考资料 效果一览 文章概述 1.时序预测 | Transformer时间序列预测 Matlab代码 2.单变量时间序列预测&#xff1b; 3.多指标评价&#xff0c;评价指标包括&#xff1a;R2、MAE、MBE等&#xff0c;代码质量极高&#xff1b; 4.excel数据&…

Git使用总结(不断更新中)

branch 本地分支操作 删除本地分支 git branch -d <local-branch-name>远端分支操作 从远端分支创建本地分支 git checkout -b <local-branch-name> origin/<remote-branch-name>git ignore 如果工程的代码文件中有不希望上传到远端的文件&#xff0c;…

Java数据类型以及范围

数据类型&#xff1a; 取值范围&#xff1a; 取值&#xff1a;

将 Notepad++ 添加到右键菜单

目录 方式一&#xff1a;添加注册表&#xff08;手动&#xff09; 方式二&#xff1a;添加注册表&#xff08;一键添加&#xff09; 有时安装了notepad后&#xff0c;在txt文件上右键&#xff0c;在弹出的菜单栏中没有【通过 Notepad 打开】&#xff0c;如下&#xff1a; 这…

c语言基础总结

1. c语言概述 c语言是计算机编程语言的一种&#xff0c;编程语言用于人和机器交流。 1.1 c语言特点 简洁 ​ c语言的语法简单&#xff0c;语句清晰明了&#xff0c;使得程序易于阅读和理解 高效 ​ c语言的执行效率高&#xff0c;可以用于开发需要高性能的应用程序 可移…

[C++][算法基础]求约数(试除法)

给定 n 个正整数 &#xff0c;对于每个整数 &#xff0c;请你按照从小到大的顺序输出它的所有约数。 输入格式 第一行包含整数 n。 接下来 n 行&#xff0c;每行包含一个整数 。 输出格式 输出共 n 行&#xff0c;其中第 i 行输出第 i 个整数 的所有约数。 数据范围 1≤…

Django模型的字段类型

Django模型中最重要并且也是唯一必须执行的就是字段定义。字段在类中进行定义&#xff0c;对应于实体数据库的字段。另外&#xff0c;定义模型字段名时为了避免冲突&#xff0c;不建议使用模型API中已经定义的关键字。 字段类型用以指定数据库的数据类型&#xff0c;例如Integ…

瑞芯微RK3328(ROC-RK3328-PC)buildroot 开发QT的hello world

第一部分&#xff1a;编译rk3328 sdk 0. 环境 - EC-R3328PC&#xff08;ROC-RK3328-PC&#xff09; - ubuntu18&#xff08;100GB&#xff09; 1. 安装依赖 sudo apt-get updatesudo apt-get install repo git-core gitk git-gui gcc-arm-linux-gnueabihf u-boot-tools devi…

C++ //练习 12.26 用allocator重写第427中的程序。

C Primer&#xff08;第5版&#xff09; 练习 12.26 练习 12.26 用allocator重写第427中的程序。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /************************************************************************…

Linux入门攻坚——19、sed入门、bash脚本编程续

sed&#xff1a;Stream EDitor&#xff0c;流编辑器&#xff0c;行编辑器&#xff1a;实现文本编辑时是逐行进行的。 用法&#xff1a; sed [option]... script inputfile... script&#xff1a;‘地址命令’&#xff0c;如1,4d sed是将文件内容读取后放入自己的编辑…