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

发布时间 2024-01-03 16:33:53作者: 霸道流氓

场景

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

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/135359035

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

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/129322345

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

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

 

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi

实现

1、Fleck

https://github.com/statianzo/Fleck

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