首页 > 编程语言 >C# WebSocket的简单使用【使用Fleck实现】

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

时间:2024-11-06 19:30:04浏览次数:1  
标签:clientUrl WebSocket string C# void private Fleck ._ public

有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

 

 

 

 

 

 

 

 

 

标签:clientUrl,WebSocket,string,C#,void,private,Fleck,._,public
From: https://www.cnblogs.com/ywtssydm/p/18525218

相关文章

  • 零基础‘自外网到内网’渗透过程详细记录(cc123靶场)——上
    一、网络环境示意图二、环境搭建首先将三个虚拟机使用VMware打开。接下来对虚拟机进行配置。首先配置虚拟机“护卫神主机大师(项目四)”。点击编辑虚拟机设置。发现存在两个网卡。打开虚拟网络编辑器。点击更改设置。点击添加网络。选择VM19后点击确定。根......
  • c语言中多个变量连续赋值
     001、[root@PC1test]#lstest.c[root@PC1test]#cattest.c##测试c程序#include<stdio.h>intmain(void){inti,j;i=j=5;//连续赋值printf("i=%d\n",i);printf("j=%......
  • Scala的高阶函数
    在函数式编程中,高阶函数(Higher-OrderFunction)是核心概念之一,它们可以接受其他函数作为参数,或者返回函数作为结果358。这使得函数可以像普通值一样被传递和操作,从而实现更灵活和抽象的编程方式56。 在Scala中实现高阶函数1.作为参数的函数:在Scala中,函数可以作为参数传递给......
  • 第十届中国大学生程序设计竞赛 哈尔滨站(CCPC 2024 Harbin Site)
    B.ConcaveHull题目描述简单多边形是平面中由线段组成的闭合曲线,这些线段首尾相连,除了因连接共用的线段端点,任何两个线段都不能彼此相交。简单多边形可以分为两类:凸多边形和凹多边形。一个凸多边形是指:多边形中任意两点间的线段上的所有点都在多边形内,包括在内部或边界上。......
  • 对C++程序使用输入输出重定向
    一般来说,在VisualStudio使用文件重定向有三种方法:方法一:通过命令行参数实现项目→属性→配置属性→调试→命令参数然后就在这里加上你的命令行参数比如我有这样一段程序:#include<iostream>#include<fstream>#include"Sales_item.h"intmain(){ Sales_itemtrans1,......
  • Scala作业
    importscala.collection.mutable//1.创建一个可变Map,用于存储图书馆中的书籍信息(键为书籍编号,值为包含书籍名称、作者、库存数量的元组),初始化为包含几本你喜欢的书籍信息。//2.使用+=操作符添加两本新的书籍到图书馆集合中。//3.根据书籍编号查询某一本特定的书籍信......
  • 0基础学Python——面向对象-可迭代、面向对象-迭代器、call方法、call方法实现装饰器
    0基础学Python——面向对象-可迭代、面向对象-迭代器、call方法、call方法实现装饰器、计算函数运行时间面向对象--可迭代实现方法面向对象--迭代器实现方法call方法作用call方法实现装饰器代码演示计算函数运行时间代码演示面向对象–可迭代把对象看做容器,存储......
  • 基于卷积神经网络的柑桔病害识别与防治系统,resnet50,mobilenet模型【pytorch框架+pytho
     更多目标检测和图像分类识别项目可看我主页其他文章功能演示:柑橘病害识别与防治系统,卷积神经网络,resnet50,mobilenet【pytorch框架,python源码】_哔哩哔哩_bilibili(一)简介基于卷积神经网络的柑桔病害识别与防治系是在pytorch框架下实现的,这是一个完整的项目,包括代码,数据集,......
  • Context的典型使用场景
    获取应用文件路径基类Context提供了获取应用文件路径的能力,ApplicationContext、AbilityStageContext、UIAbilityContext和ExtensionContext均继承该能力。应用文件路径属于应用沙箱路径,上述各类Context获取的应用文件路径有所不同。通过ApplicationContext获取应用级别的应用文......
  • c语言中声明数组时, 元素个数必须使用常量表达式
     001、[root@PC1test]#lstest.c[root@PC1test]#cattest.c##测试程序#include<stdio.h>intmain(void){intvar1=5;//初始化一个变量var1intarray1[var1]={3,5,8,4,9};//初始化数组return0;}[......