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;
        }

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

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

相关文章

计算机基础面试题 |08.精选计算机基础面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

前端框架中的状态管理(State Management)

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

【算法每日一练]-dfs bfs(保姆级教程 篇8 )#01迷宫 #血色先锋队 #求先序排列 #取数游戏 #数的划分

目录 今日知识点&#xff1a; 使用并查集映射点&#xff0c;构造迷宫的连通块 vis计时数组要同步当回合的处理 递归求先序排列 基于不相邻的取数问题&#xff1a;dfs回溯 n个相同球放入k个相同盒子&#xff1a;dfs的优化分支暴力 01迷宫 血色先锋队 求先序排列 取数游…

【ikbp】数据可视化DataV

天天查询一些数据&#xff0c;希望来一个托拉拽的展示&#xff0c;部署体验一下可视化大屏 快速搭建快速查询实时更新简单易用 启动服务 数据可视化 静态查询 配置数据 过滤数据 分享

计算机网络—网络搭建NAT内外网映射

使用Windows Server 2003 网络拓扑 Router 外网&#xff1a;NAT IP 网段 192.168.17.0/24内网&#xff1a;仅主机模式 IP 172.16.29.4 Client1&#xff1a;仅主机模式 IP 172.16.29.2 网关 172.16.29.1 Client2&#xff1a;仅主机模式 IP 172.16.29.3 网关 172.16.29.1…

数字信号处理期末复习——计算小题(二)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

uni-app中实现元素拖动

uni-app中实现元素拖动 1、代码示例 <template><movable-area class"music-layout"><movable-view class"img-layout" :x"x" :y"y" direction"all"><img :src"musicDetail.bgUrl" :class&…

SpringBoot实现Websocket聊天交友微信小程序(一)

记录一下我开发一个交友微信小程序并且上线运营的心得体会。 2022年10月1日上线的&#xff0c;到目前终于实现每天收益300左右。 界面比较简洁&#xff0c;功能有动态&#xff0c;动态可以选择话题&#xff0c;相册&#xff0c;相册可以设置看广告解锁&#xff0c;私信&#…

Kubernetes-网络

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

59.网游逆向分析与插件开发-游戏增加自动化助手接口-文字资源读取类的C++还原

内容来源于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;游戏菜单文字资源读取的逆向分析-CSDN博客 之前的内容&#xff1a;接管游戏的自动药水设定功能-CSDN博客 码云地址&#xff08;master分支&#xff09;&#xff1a;https://gitee.com/dye_your_fing…

2 Windows网络编程

1 基础概念 1.1 socket概念 Socket 的原意是“插座”&#xff0c;在计算机通信领域&#xff0c;socket 被翻译为“套接字”&#xff0c;它是计算机之间进行通信的一种约定或一种方式。Socket本质上是一个抽象层&#xff0c;它是一组用于网络通信的API&#xff0c;包括了一系列…

2024——剑之所至,所向披靡

目录 *年度总结导航 一.开篇——写在篇头 二.工作篇——心之所向 1.CSDN记录篇 1,1博客主页 1.2 第一篇博文 1.3.产品测试 1.4C站获奖博文 1.5团队创建 2.腾讯云记录篇 2.1博主的主页 2.2 博主好文推荐 2.3腾讯云产品体验 三.励志篇——未来可期 2023年计划 …

苹果cmsV10暗黑大气MT主题模板源码-只有PC版本

苹果cms MT主题是一款多功能苹果cmsV10暗黑大气主题 初次使用说明&#xff1a; 网站模板选择mt 模板目录填写html 后台地址&#xff1a;MT主题,mt/mtset 先应用主题打开前台&#xff0c;再点击后台。 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725…

网络安全—部署CA证书服务器

文章目录 网络拓扑安装步骤安装证书系统安装从属证书服务器 申请与颁发申请证书CA颁发证书 使用windows Server 2003环境 网络拓扑 两台服务器在同一网段即可&#xff0c;即能够互相ping通。 安装步骤 安装证书系统 首先我们对计算机名进行确认&#xff0c;安装了证书系统后我…

阿里云服务器8080端口安全组开通图文教程

阿里云服务器8080端口开放在安全组中放行&#xff0c;Tomcat默认使用8080端口&#xff0c;8080端口也用于www代理服务&#xff0c;阿腾云atengyun.com以8080端口为例来详细说下阿里云服务器8080端口开启教程教程&#xff1a; 阿里云服务器8080端口开启教程 阿里云服务器8080端…

如何在Mendix中实现全文检索

功能背景 在日常的应用使用过程中&#xff0c;存在大量希望使用全文检索技术的场景&#xff0c;对资料库中的内容进行查询。Mendix默认的结构化查询方式&#xff0c;适合对特定业务实体进行类似数据库单表的基于SQL语句的查询。那如何在Mendix实现全文检索的功能呢&#…

13.Go 异常

1、宕机 Go语言的类型系统会在编译时捕获很多错误&#xff0c;但有些错误只能在运行时检查&#xff0c;如数组访问越界、空指针引用等&#xff0c;这些运行时错误会引起宕机。 一般而言&#xff0c;当宕机发生时&#xff0c;程序会中断运行&#xff0c;并立即执行在该gorouti…

rk3588中编译带有ffmpeg的opencv

有朋友有工程需要&#xff0c;将视频写成mp4&#xff0c;当然最简单的方法当然是使用opencv的命令 cv::VideoWriter writer;bool bRet writer.open("./out.mp4", cv::VideoWriter::fourcc(m, p, 4, v), 15, cv::Size(640, 512), 1); 但是奈何很难编译成功&#xff…

go执行静态二进制文件和执行动态库文件

目的和需求&#xff1a;部分go的核心文件不开源&#xff0c;例如验证&#xff0c;主程序核心逻辑等等 第一个想法&#xff0c;把子程序代码打包成静态文件&#xff0c;然后主程序执行 子程序 package mainimport ("fmt""github.com/gogf/gf/v2/os/gfile"…

云服务器评估迁移时间与测试传输速度

迁移周期主要分为迁移前、迁移过程中、迁移后三部分。迁移周期时长与待迁移服务器的数量和实际数据量成正比&#xff0c;建议您根据实际迁移测试演练进行评估。本文主要介绍迁移过程中这一阶段所需时间的评估方式和传输速度的测试方法。 背景信息 在SMC迁移过程中&#xff0c…