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