C# WebSocket的简单使用【使用Fleck实现】

news/2024/12/25 1:33:55/文章来源:https://www.cnblogs.com/ywtssydm/p/18525218

有bug,不推荐使用

有bug,不推荐使用

有bug,不推荐使用

2.WebSocketHelper

新建 WebSocketHelper.cs

using Fleck;namespace WebSocket
{internal class WebSocketHelper{//客户端url以及其对应的Socket对象字典IDictionary<string, IWebSocketConnection> dic_Sockets = new Dictionary<string, IWebSocketConnection>();//创建一个 websocket ,0.0.0.0 为监听所有的的地址WebSocketServer server = new WebSocketServer("ws://0.0.0.0:30000");//打开连接委托public delegate void _OnOpen(string ip);public event _OnOpen OnOpen;//关闭连接委托public delegate void _OnClose(string ip);public event _OnClose OnClose;//当收到消息public delegate void _OnMessage(string ip, string msg);public event _OnMessage OnMessage;/// <summary>/// 初始化/// </summary>private void Init(){//出错后进行重启server.RestartAfterListenError = true;//开始监听server.Start(socket =>{//连接建立事件socket.OnOpen = () =>{//获取客户端网页的urlstring clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;dic_Sockets.Add(clientUrl, socket);if (OnOpen != null) OnOpen(clientUrl);Console.WriteLine(DateTime.Now.ToString() + " | 服务器:和客户端:" + clientUrl + " 建立WebSock连接!");};//连接关闭事件socket.OnClose = () =>{string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;//如果存在这个客户端,那么对这个socket进行移除if (dic_Sockets.ContainsKey(clientUrl)){dic_Sockets.Remove(clientUrl);if (OnClose != null) OnClose(clientUrl);}Console.WriteLine(DateTime.Now.ToString() + " | 服务器:和客户端:" + clientUrl + " 断开WebSock连接!");};//接受客户端网页消息事件socket.OnMessage = message =>{string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;Receive(clientUrl, message);if (OnMessage != null) OnMessage(clientUrl, message);};});}/// <summary>/// 向客户端发送消息/// </summary>/// <param name="webSocketConnection">客户端实例</param>/// <param name="message">消息内容</param>public void Send(string clientUrl, string message){IWebSocketConnection webSocketConnection = GetUserSocketInstance(clientUrl);if (webSocketConnection != null){if (webSocketConnection.IsAvailable){webSocketConnection.Send(message);}}}/// <summary>/// 接收消息/// </summary>/// <param name="clientUrl"></param>/// <param name="message"></param>private void Receive(string clientUrl, string message){Console.WriteLine(DateTime.Now.ToString() + " | 服务器:【收到】来客户端:" + clientUrl + "的信息:\n" + message);}/// <summary>/// 获取用户实例/// </summary>/// <param name="clientUrl">用户的地址</param>public IWebSocketConnection GetUserSocketInstance(string clientUrl){if (dic_Sockets.ContainsKey(clientUrl))return dic_Sockets[clientUrl];elsereturn null;}/// <summary>/// 关闭某一个用户的连接/// </summary>/// <param name="clientUrl"></param>public void CloseUserConnect(string clientUrl){IWebSocketConnection webSocketConnection = GetUserSocketInstance(clientUrl);if (webSocketConnection != null)webSocketConnection.Close();}/// <summary>/// 关闭与客户端的所有的连接/// </summary>public void CloseAllConnect(){foreach (var item in dic_Sockets.Values){if (item != null){item.Close();}}}public WebSocketHelper(){Init();}}
}

3.Program

目前并没有写入太多功能,只是加了控制台输入文字,然后转发给所有连接的用户

using WebSocket;namespace WebSocketNet6
{internal class Program{private static List<string> IPList = new List<string>();private static WebSocketHelper WebSocketHelpers = new WebSocketHelper();static void Main(string[] args){WebSocketHelpers.OnOpen += WebSocketHelper_OnOpen;WebSocketHelpers.OnClose += WebSocketHelper_OnClose;WebSocketHelpers.OnMessage += WebSocketHelper_OnMessage;while (true){//监听控制台的输入string? contetn = Console.ReadLine();if (contetn != null){Relay(contetn);if (contetn.Equals("q")){WebSocketHelpers.CloseAllConnect();Console.WriteLine("关闭所有客户端的连接");break;}}Thread.Sleep(10);}}#region WebSocket回调//当收到消息private static void WebSocketHelper_OnMessage(string ip, string msg){for (int i = 0; i < IPList.Count; i++){if (IPList[i] != ip){WebSocketHelpers.Send(IPList[i], msg);}}}//当客户端断开连接private static void WebSocketHelper_OnClose(string ip){if (IPList.Contains(ip)){IPList.Remove(ip);}}//当客户端连接上服务器private static void WebSocketHelper_OnOpen(string ip){if (!IPList.Contains(ip)){IPList.Add(ip);}}#endregion//转发所有客户端private static void Relay(string content){if (IPList.Count == 0)  return;for (int i = 0; i < IPList.Count; i++){WebSocketHelpers.Send(IPList[i], content);}}}
}

三、客户端

1.html

 
<!DOCTYPE  HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head><title>websocket client</title><script type="text/javascript">var start = function () {var inc = document.getElementById('incomming');var wsImpl = window.WebSocket || window.MozWebSocket;var form = document.getElementById('sendForm');var input = document.getElementById('sendText');inc.innerHTML += "连接服务器..<br/>";// 创建一个新的websocket并连接window.ws = new wsImpl('ws://localhost:30000/');// 当数据来自服务器时,将调用此方法ws.onmessage = function (evt) {inc.innerHTML += ("[来自服务器的消息] " + evt.data + '<br/>');console.log("[来自服务器的消息] " + evt.data);};// 当建立连接时,将调用此方法ws.onopen = function () {inc.innerHTML += '已建立连接.. <br/>';};// 当连接关闭时,将调用此方法ws.onclose = function () {inc.innerHTML += '连接已关闭.. <br/>';}form.addEventListener('submit', function (e) {e.preventDefault();var val = input.value;ws.send(val);input.value = "";});}window.onload = start;</script>
</head>
<body><form id="sendForm"><span>输入内容按回车发送消息</span> <br/><input id="sendText" placeholder="Text to send" /></form><pre id="incomming"></pre>
</body>
</html>

2.Winform

新建一个 winform 项目

先安装插件 SuperSocket.ClientEngine

using SuperSocket.ClientEngine;
using System;
using System.Threading;
using System.Threading.Tasks;
using WebSocket4Net;namespace WebSocketClient
{public class WSocketClient : IDisposable{//收到消息后的回调//public event Action<string> MessageReceived;public Action<string> MessageReceived;private WebSocket4Net.WebSocket _webSocket;/// <summary>/// 检查重连线程/// </summary>
        Thread _thread;bool _isRunning = false;/// <summary>/// 是否在运行中/// </summary>public bool IsRunning => _isRunning;/// <summary>/// WebSocket连接地址/// </summary>public string ServerPath { get; set; }public WSocketClient(string url){ServerPath = url;this._webSocket = new WebSocket4Net.WebSocket(url);this._webSocket.Opened += WebSocket_Opened;this._webSocket.Error += WebSocket_Error;this._webSocket.Closed += WebSocket_Closed;this._webSocket.MessageReceived += WebSocket_MessageReceived;}/// <summary>/// 连接方法/// <returns></returns>public bool Start(){bool result = true;try{this._webSocket.Open();this._isRunning = true;this._thread = new Thread(new ThreadStart(CheckConnection));this._thread.Start();}catch (Exception ex){Console.WriteLine(ex.ToString());result = false;this._isRunning = false;}return result;}/// <summary>/// 消息收到事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void WebSocket_MessageReceived(object sender, MessageReceivedEventArgs e){Console.WriteLine("Received:" + e.Message);if (MessageReceived != null)MessageReceived(e.Message);}/// <summary>/// Socket关闭事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void WebSocket_Closed(object sender, EventArgs e){Console.WriteLine("websocket_Closed");}/// <summary>/// Socket报错事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void WebSocket_Error(object sender, ErrorEventArgs e){Console.WriteLine("websocket_Error:" + e.Exception.ToString());}/// <summary>/// Socket打开事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void WebSocket_Opened(object sender, EventArgs e){Console.WriteLine("websocket_Opened");}/// <summary>/// 检查重连线程/// </summary>private void CheckConnection(){do{try{if (this._webSocket.State != WebSocket4Net.WebSocketState.Open && this._webSocket.State != WebSocket4Net.WebSocketState.Connecting){Console.WriteLine("Reconnect websocket WebSocketState:" + this._webSocket.State);this._webSocket.Close();this._webSocket.Open();Console.WriteLine("正在重连");}}catch (Exception ex){Console.WriteLine(ex.ToString());}System.Threading.Thread.Sleep(5000);} while (this._isRunning);}/// <summary>/// 发送消息/// </summary>/// <param name="Message"></param>public void SendMessage(string Message){Task.Factory.StartNew(() =>{if (_webSocket != null && _webSocket.State == WebSocket4Net.WebSocketState.Open){this._webSocket.Send(Message);}});}public void Dispose(){try{_thread?.Abort();}catch (Exception ex){Console.WriteLine(ex.Message);}this._webSocket.Close();this._webSocket.Dispose();this._webSocket = null;this._isRunning = false;}}
}

using System;
using System.Windows.Forms;
using WebSocketClient;namespace WinFormWebsocket
{public partial class Form1 : Form{private static string url = "ws://127.0.0.1:30000";private WSocketClient client = new WSocketClient(url);public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){Control.CheckForIllegalCrossThreadCalls = false;txtServerIP.Text = url;client.MessageReceived = MessageReceived;this.Text = "客户端";}private void Form1_FormClosing(object sender, FormClosingEventArgs e){if(client.IsRunning)client.Dispose();}/// <summary>/// 连接服务器/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btnConnect_Click(object sender, EventArgs e){try{if(client.IsRunning){AddOrdinaryLog("已经连接服务器,不能重复执行");return;}bool result = client.Start();AddOrdinaryLog("连接是否成功:" + result);}catch (Exception ex){string err = string.Format("连接失败:{0}", ex.Message);Console.WriteLine(err);throw;}}/// <summary>/// 关闭服务器/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btnClose_Click(object sender, EventArgs e){if (!client.IsRunning){AddOrdinaryLog("服务器未连接");return;}// 记得释放资源否则会造成堆栈
            client.Dispose();AddOrdinaryLog("连接已关闭");}/// <summary>/// 发送消息/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btnSendMsg_Click(object sender, EventArgs e){string inputMsg = txtInputMsg.Text;if (string.IsNullOrEmpty(inputMsg)){MessageBox.Show("输入框不能为空");return;}client.SendMessage(inputMsg);AddOrdinaryLog(inputMsg);txtInputMsg.Text = string.Empty;}/// <summary>/// 服务端返回的消息/// </summary>private void MessageReceived(string msg){AddOrdinaryLog(msg);}/// <summary>/// 添加日志/// </summary>/// <param name="content"></param>private void AddOrdinaryLog(string content){//读取当前ListBox列表长度int len = ListBox_OrdinaryLogList.Items.Count;//插入新的一行
            ListBox_OrdinaryLogList.Items.Insert(len, content);//列表长度大于30,那么就删除第1行的数据if (len > 30)ListBox_OrdinaryLogList.Items.RemoveAt(0);//插入新的数据后,将滚动条移动到最下面int visibleItems = ListBox_OrdinaryLogList.ClientSize.Height / ListBox_OrdinaryLogList.ItemHeight;ListBox_OrdinaryLogList.TopIndex = Math.Max(ListBox_OrdinaryLogList.Items.Count - visibleItems + 1, 0);}}
}

来源:https://blog.csdn.net/qq_38693757/article/details/127193349

 

 

 

 

 

 

 

 

 

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

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

相关文章

第三十五讲:为什么临时表可以重名?

创建临时表,一部分为了优化查询,join在临时表里查询出结果后导入到正常表中,他也支持多session的查询优化,更重要一点是在session会话关闭后,临时表会自动销毁。嗯就这样 另外分清他和内存表的区别 内存表一定是从memory引擎创建的,临时表可以由memory引擎创建第三十五讲…

如何理解shell命令 cd $(dirname $0)

如何理解shell命令 cd $(dirname $0)-CSDN博客

对C++程序使用输入输出重定向

一般来说,在Visual Studio使用文件重定向有三种方法: 方法一:通过命令行参数实现 项目→属性→配置属性→调试→命令参数然后就在这里加上你的命令行参数 比如我有这样一段程序: #include <iostream> #include <fstream> #include "Sales_item.h"int…

红米k70怎么设置「短信通知」在锁屏时隐藏内容,不锁屏时不隐藏内容

红米 K70 设置短信通知在锁屏时隐藏内容、不锁屏时不隐藏内容,可以按照以下步骤进行操作:打开手机设置:在主屏幕上找到并点击 “设置” 图标,进入手机设置页面。 进入通知与控制中心:在设置页面中,找到并点击 “通知与控制中心” 选项。 选择锁屏通知:在通知与控制中心页…

c语言中声明数组时, 元素个数必须使用常量表达式

001、[root@PC1 test]# ls test.c [root@PC1 test]# cat test.c ## 测试程序 #include <stdio.h>int main(void) {int var1 = 5; // 初始化一个变量var1int array1[var1] = {3,5,8,4,9}; // 初始化数组return 0; } [root@PC1 test]# gcc test.c …

图的基本操作

目录1.图2.图的结构体定义3.图的初始化4.添加顶点、删除顶点4.1添加顶点4.2删除顶点5.添加边、删除边5.1添加边5.2删除边6.打印图7.main函数 在生命旅途中,我们就像是一个个节点,被无数看不见的边相连。每一次的相识与相离,都在这张巨大的网络图中留下独特的印记。 1.图 图(…

正态分布

正态分布 1 标准正态分布 1.1概率密度函数 \[f(x) = \frac{1}{\sqrt{2\pi}}e^{-\frac{x^2}{2}} \]1.2 累计分布函数 \[F(x) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{x}e^{-\frac{t^2}{2}}dt \] 2 (一般)正态分布 2.1 概率密度函数 \[f(x) = \frac{1}{\sqrt{2\pi\sigma…

Pycharm中使用AI辅助Coding工具Aws Toolkit

一、安装插件 二、重启完了以后点击左下角的aws 三、点developer tools,双击codewhisperer中的start,点击connect 四、点击sign out,open and copy code五、跳转到网页浏览器中打开登录界面,我们在图中所示的 code 一栏中粘贴上验证码,点击"next"按钮六、没有账…

【日志分析平台】Logstash:IT-ELK日志分析平台

以下文章来源于唯云轩 ,作者唯云轩 上篇介绍了ELK日志分析平台-Elasticsearch集群的搭建,本篇章为大家介绍Logstash的安装 服务器规划及Elasticsearch集群搭建参考上一篇:IT-ELK日志分析平台-Elasticsearch集群 Logstash安装步骤如下官网下载安装包下载地址: (https://www.e…

Next 设置字体文件cdn 或者本地

@font-face {font-family: font-ali-bold;src: url(https://cdnurl/Alibaba-PuHuiTi-Bold.woff2) format(woff2);font-weight: normal;font-style: normal; }tailwind 设置 fontFamily 直接使用变量, 直接在className上写 font-ali 即可应用该字体 本地:// const aliF…

WPF的入门学习

环境的搭配 我们通过VS的官网来安装的VS2022,安装上C#的功能,这样就完成了环境的搭配 第一个wpf工程 打开vs2022,点击如图的创建新的工程。点选WPF的项目配置一个新的项目这样就完成了项目的创建项目结构 介绍一下大概的项目结构在APP.XAml文件中,设置我们的窗体入口界面的…

【安全架构】权限控制模型

原创 大袤宏图不同的权限模型提供了灵活的访问控制策略,本文绘制了不同模型的ER图,探讨这些模型的原理及适用场景。 一、访问控制列表模型 访问控制列表模型(Access Control List, ACL) 基于资源的访问控制列表,每个资源都有一个列表记录哪些用户可以对其进行哪些操作,适用…