C# WebSocket的简单使用【使用Fleck实现】
有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 = () => { //获取客户端网页的url string 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]; else return 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