有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