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

 

 

 

 

 

 

 

 

 

posted @ 2024-11-06 19:42  【君莫笑】  阅读(34)  评论(0编辑  收藏  举报