Winform中使用Fleck实现Websocket服务端并读取SQLite数据库中数据定时循环群发消息

场景

Winform中使用Websocket4Net实现Websocket客户端并定时存储接收数据到SQLite中:

Winform中使用Websocket4Net实现Websocket客户端并定时存储接收数据到SQLite中-CSDN博客

Winform中操作Sqlite数据增删改查、程序启动时执行创建表初始化操作:

Winform中操作Sqlite数据增删改查、程序启动时执行创建表初始化操作_winform sqllite-CSDN博客

在上面实现Websocket客户端的基础上,如何实现Websocket服务端,并实现定时给所有的客户端群发消息。

群发的消息从SQLite中读取,循环进行群发。

注:

博客:
霸道流氓气质_C#,架构之路,SpringBoot-CSDN博客

实现

1、Fleck

GitHub - statianzo/Fleck: C# Websocket Implementation

新建Winform项目,并使用Nuget引入依赖

搜索Fleck

按照官网说明,快速实现Websocket服务端只需要

var server = new WebSocketServer("ws://0.0.0.0:8181");
server.Start(socket =>
{socket.OnOpen = () => Console.WriteLine("Open!");socket.OnClose = () => Console.WriteLine("Close!");socket.OnMessage = message => socket.Send(message);
});

并且官方提供了一些示例demo,比如群发消息的实现,这里是在控制台项目中的示例

            var allSockets = new List<IWebSocketConnection>();var server = new WebSocketServer("ws://0.0.0.0:8181");server.Start(socket =>{socket.OnOpen = () =>{Console.WriteLine("Open!");allSockets.Add(socket);};socket.OnClose = () =>{Console.WriteLine("Close!");allSockets.Remove(socket);};socket.OnMessage = message =>{Console.WriteLine(message);allSockets.ToList().ForEach(s => s.Send("Echo: " + message));};});

demo位置

2、这里基于Winform设计窗体布局如下

3、启动服务端/开始监听按钮点击事件

新建WebSocketServer服务端对象,便于停止监听

public WebSocketServer wsServer= null;

新建一个list用来存储所有的客户端连接信息

private List<IWebSocketConnection> allSockets = new List<IWebSocketConnection>();

然后在开始监听按钮的点击事件中

        private void button_start_listen_Click(object sender, EventArgs e){try{allSockets.Clear();string wsAddress = textBox_server_address.Text.Trim();wsServer = new WebSocketServer(wsAddress);    //创建webscoket服务端实例wsServer.Start(socket => {socket.OnOpen = () =>{//Console.WriteLine("Open");allSockets.Add(socket);};socket.OnClose = () =>{//Console.WriteLine("Close");allSockets.Remove(socket);};socket.OnMessage = message => {//Console.WriteLine(message);                  };socket.OnError = message =>{//Console.WriteLine(message);};});textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":监听成功");textBox_log.AppendText("\r\n");}catch (Exception exception){textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":监听异常:" + exception.Message);textBox_log.AppendText("\r\n");}         }

在建立连接和关闭事件中分别对客户端的list进行添加和删除。

4、停止监听的按钮点击事件中

遍历所有客户端的list,循环进行关闭,并销毁服务端对象

        private void button_stop_listen_Click(object sender, EventArgs e){allSockets.ToList().ForEach(s => s.Close());wsServer.Dispose();textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":监听停止");textBox_log.AppendText("\r\n");}

5、单次群发按钮点击事件

        private void button_single_mass_Click(object sender, EventArgs e){if (null != wsServer){string message = textBox_message.Text.Trim();allSockets.ToList().ForEach(s => {if (s.IsAvailable){s.Send(message);}});}else {textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":wsServer未启动");textBox_log.AppendText("\r\n");}}

判断服务端对象不为空,遍历所有客户端list,判断如果可用则调用send方法,发送string类型的消息。

6、加载数据按钮实现

用来从SQLite中读取需要循环群发的消息内容

首先声明string的list用来存储加载的数据

private List<string> loadDataList = new List<string>();

然后按钮的点击事件中

        private void button_load_data_Click(object sender, EventArgs e){try{if (null == wsServer){textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":wsServer未启动");textBox_log.AppendText("\r\n");}else{loadDataList.Clear();SQLiteDataReader reader = Global.Instance.sqlLiteHelper.ExecuteQuery("SELECT* FROM positions;");if (reader.HasRows){while (reader.Read()){string data = reader.GetString(reader.GetOrdinal("data"));loadDataList.Add(data);}}textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":加载数据完成,共("+ loadDataList.Count+")条。");textBox_log.AppendText("\r\n");}}catch (Exception exception){textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":加载数据异常:" + exception.Message);textBox_log.AppendText("\r\n");}}

7、定时群发实现

首先新建定时器以及加载的数据的索引

Timer _timerMass = new Timer();private int index = 0;

定时群发按钮点击事件实现

        private void button_start_mass_Click(object sender, EventArgs e){if (null == wsServer) {textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":wsServer未启动");textBox_log.AppendText("\r\n");} else {_timerMass.Interval = (int)numericUpDown_mass.Value;_timerMass.Tick += _timer_Tick_Mass;_timerMass.Start();textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":定时群发已经启动!!");textBox_log.AppendText("\r\n");}}

定时器执行方法具体实现

        private void _timer_Tick_Mass(object sender, EventArgs e){if (loadDataList.Count>0) {if (index > loadDataList.Count - 1){index = 0;}string data = loadDataList[index];allSockets.ToList().ForEach(s => {if (s.IsAvailable) {s.Send(data);}             });index++;}}

8、停止定时群发按钮点击事件实现

        private void button_stop_mass_Click(object sender, EventArgs e){//停止定时器_timerMass.Tick -= _timer_Tick_Mass;_timerMass.Stop();textBox_log.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":定时群发已经停止!!!");textBox_log.AppendText("\r\n");index = 0;}

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

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

相关文章

docker 安装可视化工具 Portainer 以及 汉化

安装portainer是最新版本&#xff0c;汉化指定版本2.9.1 。如果要安装汉化版&#xff0c;可直接跳转步骤四 一、拉去镜像 安装网址&#xff1a;Install Portainer BE with Docker on Linux - Portainer Documentation docker pull portainer/portainer二、根据portainer镜像创建…

利用 PEB_LDR_DATA 结构枚举进程模块信息

1. 引言 我们常常通过很多方法来获取进程的模块信息&#xff0c;例如 EnumProcessModules 函数、CreateToolhelp32Snapshot 函数、WTSEnumerateProcesses 函数、ZwQuerySystemInformation 函数等。但是调用这些接口进行模块枚举的原理是什么我们并不知道。通过学习 PEB 中 PEB…

Prometheus-AlertManager 邮件告警

环境,软件准备 本次演示环境&#xff0c;我是在虚拟机上安装 Linux 系统来执行操作&#xff0c;以下是安装的软件及版本&#xff1a; System: CentOS Linux release 7.6Docker: 24.0.5Prometheus: v2.37.6Consul: 1.6.1 docker 安装prometheus,alertmanage,说明一下这里直接将…

ArrayList学生管理系统

文章目录 1.ArrayList集合和数组的优势对比&#xff1a;1.1 ArrayList类概述1.2 ArrayList类常用方法1.2.1 构造方法1.2.2 成员方法1.2.3 示例代码 1.3 ArrayList存储字符串并遍历1.3.1 案例需求1.3.2 代码实现 1.4 ArrayList存储学生对象并遍历1.4.1 案例需求1.4.2 代码实现 1…

【LLM】大型语言模型综述论文

今天我将与大家分享一篇精彩的论文。这项调查提供了LLM文献的最新综述&#xff0c;这对研究人员和工程师来说都是一个有用的资源。 为什么选择LLM&#xff1f; 当参数尺度超过一定水平时&#xff0c;这些扩展的语言模型不仅实现了显著的性能改进&#xff0c;而且还表现出一些…

uniCloud 云数据库(新建表、增、删、改、查)

新建表结构描述文件 todo 为自定义的表名 表结构描述文件的默认后缀为 .schema.json 设置表的操作权限 uniCloud-aliyun/database/todo.schema.json 默认的操作权限都是 false "permission": {"read": false,"create": false,"update&quo…

【熔断限流组件resilience4j和hystrix】

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容起因resilience4j落地实现pom.xml依赖application.yml配置接口使用 hystrix 落地实现pom.xml依赖启动类上添加注解接口上使用 &#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟…

华为HCIE-Datacom课程介绍

厦门微思网络HCIE-Datacom课程介绍 一、认证简介 HCIE-Datacom&#xff08;Huawei Certified ICT Expert-Datacom&#xff09;认证是华为认证体系中的顶级认证&#xff0c;HCIE-Datacom认证定位具备坚实的企业网络跨场景融合解决方案理论知识&#xff0c;能够使用华为数通产品…

C语言-环境搭建

文章目录 内容Notepad的安装gcc编译工具的配置 编写软件的安装&#xff1a;软件传送门&#xff1a;Notepad软件选择一个合适的路径&#xff0c;一键傻瓜式安装即可 编译工具gcc在windows环境下的配置&#xff1a;解压gcc编辑工具包解压出来的mingw64文件放到一个合适的磁盘路径…

从0到1入门C++编程——03 内存分区、引用、函数高级应用

文章目录 一、内存分区二、引用三、函数的高级应用1.默认参数2.占位参数3.函数重载 一、内存分区 C程序在执行时&#xff0c;会将内存大致分为4个区&#xff0c;分别是代码区、全局区、栈区和堆区。 代码区用来存放函数体和二进制代码&#xff0c;由操作系统进行管理。 全局区…

Kubernetes-网络

一. 前言 flannel两种容器跨主机通信的方案&#xff0c;其中UDP模式是IP in UDP&#xff0c;即三层报文封装在UDP数据包中通信&#xff1b;而vxlan模式则是MAC in UDP&#xff0c;即二层报文封装在UDP数据包中通信 flannel UDP模式和vxlan模式都对数据包做了封解包&#xff0c…

为什么我不建议大学生接公司单?

大家好&#xff0c;我是鱼皮。前两天&#xff0c;我 编程导航 的鱼友提了个问&#xff1a;大学生怎么接公司的单赚点零花钱&#xff1f; 然后我很认真地评论了一句&#xff1a;我不建议大学生接公司单。 这位小伙伴很认真&#xff0c;又通过微信单独问我&#xff1a; 想了想&am…

Mybatis行为配置之Ⅰ—缓存

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL Mybatis配置入门 Mybatis行为配置之Ⅰ—缓存 Mybatis行为配置…

【Midjourney】AI绘画新手教程(一)登录和创建服务器,生成第一幅画作

一、登录Discord 1、访问Discord官网 使用柯學尚网&#xff08;亲测非必须&#xff0c;可加快响应速度&#xff09;访问Discord官方网址&#xff1a;https://discord.com 选择“在您的浏览器中打开Discord” 然后&#xff0c;注册帐号、购买套餐等&#xff0c;在此不做缀述。…

3D目标检测(教程+代码)

随着计算机视觉技术的不断发展&#xff0c;3D目标检测成为了一个备受关注的研究领域。与传统的2D目标检测相比&#xff0c;3D目标检测可以在三维空间中对物体进行定位和识别&#xff0c;具有更高的准确性和适用性。本文将介绍3D目标检测的相关概念、方法和代码实现。 一、3D目…

Python消消乐小游戏(PyGame)

文章目录 写在前面喜羊羊与灰太狼PyGame入门消消乐注意事项写在后面 写在前面 本期内容&#xff1a;基于pygame实现喜羊羊与灰太狼版消消乐小游戏 实验环境 python3.11及以上pycharmpygame 安装pygame的命令&#xff1a; pip install -i https://pypi.tuna.tsinghua.edu.c…

Redis (三)

1、redis复制 简单的概括就是主从复制&#xff0c;master以写为主&#xff0c;Slave以读为主&#xff0c;当master数据发生变化的时候&#xff0c;自动将更新的数据异步同步到其他的slave是数据库。 使用这种机制的话&#xff0c;可以做到读写分离&#xff0c;可以减轻主机负担…

chromium在中文用户名下无法编译的问题

新电脑没有太注意&#xff0c;起用户名的时候用了中文。 在编译chromium104的代码时&#xff0c;因为环境变量有中文导致编译失败&#xff1a; 因为我的电脑默认是使用gbk编码&#xff0c;而不是utf-8编码。 这个问题有三种解决办法&#xff1a; &#xff08;一&#xff09;把…

CMake入门教程【核心篇】添加依赖(add_dependencies)

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本文的内容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1. 基本用法2. 添加目…

DBA技术栈(二):MySQL 存储引擎

2.1 MySQL存储引擎概述 上个业余的图&#xff1a; MyISAM 存储引擎是 MySQL 默认的存储引擎&#xff0c;也是目前 MySQL 使用最为广泛的存储引擎之一。他的前身就是我们在 MySQL 发展历程中所提到的 ISAM&#xff0c;是 ISAM 的升级版本。在 MySQL最开始发行的时候是 ISAM 存…