c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用

c# superwebsocket服务端可以寄宿在控制台程序、窗体程序、Windows服务
c# websocket客户端可以是控制台程序、窗体程序、Windows服务、html、手机,能连上websocket的就行了
服务端可以开启wss安全链接

如果想做即时通讯,双工通讯,或者因为频繁发送http请求导致的web服务器承受不住,都可以转用websocket

websocket 有良好的交互体验,快速的数据传输
websocket 开发简单,部署方便,上手没难度

我这里展示了,把websocket服务端寄宿在Windows服务里,客户端则用控制台访问和用web访问,调试阶段,为了避免频繁停启Windows服务,所以我用控制台启动了服务端,生产环境就可以直接把exe执行文件注册成服务了

底部有源代码百度盘下载,Windows服务安装方法
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第1张图片
1.服务端
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第2张图片

把websocket服务端类,拷贝到项目里

using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketEngine;
using SuperWebSocket;
using System;
using System.Threading;
using System.Threading.Tasks;
//install-package SuperWebSocket
//install-package nlog
//install-package nlog.config
namespace WebSocketService
{
    public class WSocketServer:IDisposable
    {
        public static NLog.Logger _Logger = NLog.LogManager.GetCurrentClassLogger();

        #region 向外传递数据事件
        public event Action MessageReceived;
        public event Action NewConnected;
        public event Action Closed;
        #endregion

        public WebSocketServer WebSocket;

        Thread _thread;
        bool _isRunning = true;


        public WSocketServer()
        {
        }

        #region WebSockertServer
        /// 
        /// 开启服务端
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public bool Open(int port, string serverName, bool isUseCertificate = false, string serverStoreName = "", string serverSecurity = "", string serverThumbprint = "")
        {
            bool isSetuped = false;
            try
            {
                this.WebSocket = new WebSocketServer();
                var serverConfig = new ServerConfig
                {
                    Name = serverName,
                    MaxConnectionNumber = 10000, //最大允许的客户端连接数目,默认为100。
                    Mode = SocketMode.Tcp,
                    Port = port, //服务器监听的端口。
                    ClearIdleSession = false,   //true或者false, 是否清除空闲会话,默认为false。
                    ClearIdleSessionInterval = 120,//清除空闲会话的时间间隔,默认为120,单位为秒。
                    ListenBacklog = 10,
                    ReceiveBufferSize = 64 * 1024, //用于接收数据的缓冲区大小,默认为2048。
                    SendBufferSize = 64 * 1024,   //用户发送数据的缓冲区大小,默认为2048。
                    KeepAliveInterval = 1,     //keep alive消息发送时间间隔。单位为秒。
                    KeepAliveTime = 60,    //keep alive失败重试的时间间隔。单位为秒。
                    SyncSend = false
                };
                SocketServerFactory socketServerFactory = null;
                //开启wss 使用证书
                if (isUseCertificate)
                {
                    serverConfig.Security = serverSecurity;
                    serverConfig.Certificate = new SuperSocket.SocketBase.Config.CertificateConfig
                    {
                        StoreName = serverStoreName,
                        StoreLocation = System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine,
                        Thumbprint = serverThumbprint
                    };
                    socketServerFactory = new SocketServerFactory();
                }
                isSetuped = this.WebSocket.Setup(new RootConfig(),serverConfig, socketServerFactory);
                if (isSetuped)
                {
                    _Logger.Info("Setup Success...");
                }
                else
                {
                    _Logger.Error("Failed to setup!");
                }
                this.WebSocket.NewSessionConnected += NewSessionConnected;
                this.WebSocket.NewMessageReceived += NewMessageReceived;
                this.WebSocket.SessionClosed += SessionClosed;
                isSetuped = this.WebSocket.Start();
                if (isSetuped)
                {
                    _Logger.Info("Start Success...");
                    _Logger.Info("Server Listen at " + this.WebSocket.Listeners[0].EndPoint.Port.ToString());
                    this._isRunning = true;
                    this._thread = new Thread(new ThreadStart(ProcessMaintainance));
                    this._thread.Start();
                }
                else
                {
                    _Logger.Error("Failed to start!");
                }
            }
            catch (Exception ex)
            {
                _Logger.Error(ex.ToString());
            }
            return isSetuped;
        }
        /// 
        /// 消息触发事件
        /// 
        /// 
        /// 
        void NewMessageReceived(WebSocketSession session, string value)
        {
            try
            {
                _Logger.Info("Receive:" + value.ToString() + " ClientIP:" + session.RemoteEndPoint);
                if(value.ToString().Equals("IsHere**"))//客户端定时发送心跳,维持链接
                {
                    return;
                }
                else
                {
                    MessageReceived?.Invoke(session, value.ToString());
                }
            }
            catch (Exception e)
            {
                _Logger.Error(e.ToString());
            }
        }
        /// 
        /// 新链接触发事件
        /// 
        /// 
        void NewSessionConnected(WebSocketSession session)
        {
            try
            {
                string message = string.Format("New Session Connected:{0}, Path:{1}, Host:{2}, IP:{3}",
                    session.SessionID.ToString(), session.Path, session.Host, session.RemoteEndPoint);
                _Logger.Info(message);
                NewConnected?.Invoke(session);
                
            }
            catch (Exception e)
            {
                _Logger.Error(e.ToString());
            }
        }
        /// 
        /// 客户端链接关闭触发事件
        /// 
        /// 
        /// 
        void SessionClosed(WebSocketSession session, CloseReason value)
        {            
            string message = string.Format("Session Close:{0}, Path:{1}, IP:{2}", value.ToString(), session.Path,session.RemoteEndPoint);
            _Logger.Info(message);
            Closed?.Invoke(session);
        }

        #endregion
        /// 
        /// 关闭服务端触发事件
        /// 
        public void Dispose()
        {
            this._isRunning = false;
            foreach (WebSocketSession session in this.WebSocket.GetAllSessions())
            {
                session.Close();
            }
            try
            {
                this.WebSocket.Stop();
            }
            catch { }
        }
        /// 
        /// 输出实时连接线程
        /// 
        void ProcessMaintainance()
        {
            do
            {
                try
                {
                    _Logger.Debug("Display Session Info:" + this.WebSocket.SessionCount);
                    foreach (WebSocketSession session in this.WebSocket.GetAllSessions())
                    {
                        string message = string.Format("ID:{0}, Remote:{1}, Path:{2}, LastActiveTime:{3}, StartTime:{4}",
                            session.SessionID, session.RemoteEndPoint, session.Path
                          , session.LastActiveTime, session.StartTime);
                        _Logger.Debug(message);
                    }
                }
                catch (Exception e)
                {
                    _Logger.Error(e.ToString());
                }
                System.Threading.Thread.Sleep(5 * 60000);
            } while (this._isRunning);
        }

        /// 
        /// 发送消息
        /// 
        /// 客户端连接
        /// 消息内容

        public void SendMessage(WebSocketSession session, string message)
        {
            Task.Factory.StartNew(() =>{if (session != null && session.Connected) session.Send(message);});
        }

        
    }
}

打开控制台 按顺序安装这几个包
install-package SuperWebSocket
install-package nlog
install-package nlog.config

c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第3张图片
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第4张图片

然后写个业务逻辑类,操作websocket服务端类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WebSocketService
{
    public class BLL
    {
        WSocketServer _server = null;
        bool _isRunning = false;
        public BLL()
        {
            try
            {

                _server = new WSocketServer();
                _server.MessageReceived += Server_MessageReceived;
                _server.NewConnected += Server_NewConnected;
                _server.Closed += _server_Closed;
            }
            catch (Exception ex)
            {
                WSocketServer._Logger.Error(ex.ToString());
            }
        }

        private void _server_Closed(SuperWebSocket.WebSocketSession obj)
        {
            Console.WriteLine($"Closed {System.Web.HttpUtility.UrlDecode(obj.Path, System.Text.Encoding.UTF8)}");
        }

        private void Server_NewConnected(SuperWebSocket.WebSocketSession obj)
        {
            //对新链接做处理,验证链接是否合法等等,不合法则关闭该链接
            //新链接进行数据初始化
            
            Console.WriteLine($"NewConnected {System.Web.HttpUtility.UrlDecode(obj.Path, System.Text.Encoding.UTF8)}");
        }

        private void Server_MessageReceived(SuperWebSocket.WebSocketSession arg1, string arg2)
        {
            //接收到客户端链接发送的东西
            Console.WriteLine($"from {System.Web.HttpUtility.UrlDecode(arg1.Path, System.Text.Encoding.UTF8)} => {arg2}");
        }

        public bool Start()
        {
            _isRunning = true;
            //设置监听端口
            var result = _server.Open(1234, "MySocket");

            //模拟 服务端主动推送信息给客户端
            if (result)
            {
                Task.Factory.StartNew(() => {
                    while (_isRunning)
                    {
                        foreach (var item in _server.WebSocket.GetAllSessions()) _server.SendMessage(item,"服务器时间:"+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        System.Threading.Thread.Sleep(1000);
                    }
                });
            }
            return result;
        }
        public void Stop()
        {
            _isRunning = false;
            _server.Dispose();
        }
    }
}

然后就是在Windows服务停启时操作业务逻辑
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第5张图片
好了 一个c# websocket 服务端搭建完成了

因为这里是通过控制台来调用调试这个服务,所以要再建一个控制台项目
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第6张图片
然后选中控制台项目,ctrl+f5,启动项目,如果没什么问题,那么就搞定了,注意websocket监听的端口是可用的,我这里用了1234

2.客户端-控制台
接下来就建个控制台项目作为客户端,去连接服务端
新建控制台项目,把websocket客户端类拷进去

using SuperSocket.ClientEngine;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebSocket4Net;
//install-package WebSocket4Net
//install-package nlog
//install-package nlog.config
namespace WebSocketClient
{
   public class WSocketClient:IDisposable
    {
   		 //日志管理
        public static NLog.Logger _Logger = NLog.LogManager.GetCurrentClassLogger();

        #region 向外传递数据事件
        public event Action MessageReceived;
        #endregion

        WebSocket4Net.WebSocket _webSocket;
        /// 
        /// 检查重连线程
        /// 
        Thread _thread;
        bool _isRunning = true;
        /// 
        /// WebSocket连接地址
        /// 
        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;
        }

        #region "web socket "
        /// 
        /// 连接方法
        /// 
        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) 
            {
                _Logger.Error(ex.ToString());
                result = false;
            }
            return result;
        }
        /// 
        /// 消息收到事件
        /// 
        /// 
        /// 
        void WebSocket_MessageReceived(object sender, MessageReceivedEventArgs e) 
        {
            _Logger.Info(" Received:" +e.Message);
            MessageReceived?.Invoke(e.Message);
        }
        /// 
        /// Socket关闭事件
        /// 
        /// 
        /// 
        void WebSocket_Closed(object sender, EventArgs e) 
        {
            _Logger.Info("websocket_Closed");
        }
        /// 
        /// Socket报错事件
        /// 
        /// 
        /// 
        void WebSocket_Error(object sender, ErrorEventArgs e) 
        {
            _Logger.Info("websocket_Error:" + e.Exception.ToString());
        }
        /// 
        /// Socket打开事件
        /// 
        /// 
        /// 
        void WebSocket_Opened(object sender, EventArgs e) 
        {
            _Logger.Info(" websocket_Opened");         
        }
        /// 
        /// 检查重连线程
        /// 
        private void CheckConnection()
        {
            do
            {
                try
                {
                    if (this._webSocket.State != WebSocket4Net.WebSocketState.Open && this._webSocket.State != WebSocket4Net.WebSocketState.Connecting)
                    {
                        _Logger.Info(" Reconnect websocket WebSocketState:" + this._webSocket.State);
                        this._webSocket.Close();
                        this._webSocket.Open();
                        Console.WriteLine("正在重连");
                    }
                }
                catch (Exception ex)
                {
                    _Logger.Error(ex.ToString());
                }
                System.Threading.Thread.Sleep(5000);
            } while (this._isRunning);
        }
        #endregion

        /// 
        /// 发送消息
        /// 
        /// 
        public void SendMessage(string Message)
        {
            Task.Factory.StartNew(() =>
            {
                if (_webSocket != null && _webSocket.State == WebSocket4Net.WebSocketState.Open)
                {
                    this._webSocket.Send(Message);
                }
            });
        }

        public void Dispose()
        {
            this._isRunning = false;
            try
            {
                _thread.Abort();
            }
            catch
            {

            }
            this._webSocket.Close();
            this._webSocket.Dispose();
            this._webSocket = null;  
        }
    }
}

同样打开包管理控制台,顺序安装这几个必要的包,注意选择安装的项目名字
install-package WebSocket4Net
install-package nlog
install-package nlog.config

装完就可以开始连接服务端了
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第7张图片
3.客户端-网页





    
    


完成…
源代码下载 百度盘
链接: https://pan.baidu.com/s/1JljNBFhCWSUrtfohDbNpDA 提取码: gyj7

Windows服务安装方法
1.把项目模式改成发布模式Release
2.右键项目生成或者重新生成
3.打开项目位置,打开bin文件夹,打开Release文件夹
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第8张图片
4.把服务必备的一些组件都复制走
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第9张图片
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第10张图片
安装完成,在计算机管理-服务里面可以看到,你的服务名字,还没启动,需要手动开启,或者电脑重启后自动开启
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第11张图片
右键服务-选择第一个“启动”
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第12张图片
卸载服务,先打开服务管理,右键,停止,然后复制删除命令到cmd执行
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第13张图片
刷新一下服务列表,服务已经删除
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第14张图片
如果想要更新服务的话,要先停止服务,然后把生成后的新dll啊或者exe,覆盖掉旧的就可以了,修改配置文件的话也需要重新启动服务才能生效,停止服务需要一点时间,不能一点停止就立即覆盖,系统会报文件占用

所有步骤都完成了

这里是安装服务的工具和命令
链接: https://pan.baidu.com/s/1xBAzOcVdRmJfqaN8oCRXow 提取码: ae5z

WSS 开启介绍
add 2019年1月25日18:06:47

各参数说明,这里可以有两种方式使用证书
1.是填证书安装后的存储区名字和证书的指纹
2.是直接填证书的所在路径,和密码
目前啊 我只成功地用过路径,和密码的方式开启,
关于怎么用指纹,我还是不知道,如有哪位知道的,望相告.
另外开了wss后,需要用域名来访问,ip不行
(以上结论来于,阿里云免费试用服务器个人版 win server 2008 r2 和免费国外域名 和 阿里云上申请的免费 ssl证书…)
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第15张图片

/// 
        /// 开启服务端
        /// 
        /// 123
        /// test
        /// true 如果开启wss需要用域名访问(wss:\\abc.com:123\)
        /// My -证书安装后的存储位置(一般是“个人”)
        /// ssl/tls
        /// ‎7384a6027fa8004585c0958c7fcbcb8fd9cd27fb 证书指纹 如果指纹填空,则使用路径加载证书,否则使用指纹
        /// D:\1774183_xxx_iis\1774183_xxx.pfx 证书所在路径
        /// ABC 证书密码
        /// 
        public bool Open(int port, string serverName, bool isUseCertificate = false, string certificateStoreName = "", string security = "", string certificateThumbprint = "",string certificatePath="",string certificatePwd="")
        {
            bool isSetuped = false;
            try
            {
                this.WebSocket = new WebSocketServer();
                var serverConfig = new ServerConfig
                {
                    Name = serverName,
                    MaxConnectionNumber = 10000, //最大允许的客户端连接数目,默认为100。
                    Mode = SocketMode.Tcp,
                    Port = port, //服务器监听的端口。
                    ClearIdleSession = false,   //true或者false, 是否清除空闲会话,默认为false。
                    ClearIdleSessionInterval = 120,//清除空闲会话的时间间隔,默认为120,单位为秒。
                    ListenBacklog = 10,
                    ReceiveBufferSize = 64 * 1024, //用于接收数据的缓冲区大小,默认为2048。
                    SendBufferSize = 64 * 1024,   //用户发送数据的缓冲区大小,默认为2048。
                    KeepAliveInterval = 1,     //keep alive消息发送时间间隔。单位为秒。
                    KeepAliveTime = 60,    //keep alive失败重试的时间间隔。单位为秒。
                    SyncSend = false                    
                };
                SocketServerFactory socketServerFactory = null;
                //开启wss 使用证书
                if (isUseCertificate)
                {
                    serverConfig.Security = security;
                    //指纹不为空 则使用指纹,否则使用路径访问证书
                    if (certificateThumbprint != string.Empty)
                    {
                        serverConfig.Certificate = new SuperSocket.SocketBase.Config.CertificateConfig
                        {
                            StoreName = certificateStoreName,
                            StoreLocation = System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine,
                            Thumbprint = certificateThumbprint
                        };
                    }
                    else
                    {
                        serverConfig.Certificate = new SuperSocket.SocketBase.Config.CertificateConfig
                        {
                            FilePath = certificatePath,
                            Password = certificatePwd
                        };
                    }
                    socketServerFactory = new SocketServerFactory();
                }
                isSetuped = this.WebSocket.Setup(new RootConfig(),serverConfig, socketServerFactory);
                if (isSetuped)
                {
                    _Logger.Info("Setup Success...");
                }
                else
                {
                    _Logger.Error("Failed to setup!");
                }
                this.WebSocket.NewSessionConnected += NewSessionConnected;
                this.WebSocket.NewMessageReceived += NewMessageReceived;
                this.WebSocket.SessionClosed += SessionClosed;
                isSetuped = this.WebSocket.Start();
                if (isSetuped)
                {
                    _Logger.Info("Start Success...");
                    _Logger.Info("Server Listen at " + this.WebSocket.Listeners[0].EndPoint.Port.ToString());
                    this._isRunning = true;
                    this._thread = new Thread(new ThreadStart(ProcessMaintainance));
                    this._thread.Start();
                }
                else
                {
                    _Logger.Error("Failed to start!");
                }
            }
            catch (Exception ex)
            {
                _Logger.Error(ex.ToString());
            }
            return isSetuped;
        }

这里我使用配置文件
c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用_第16张图片

源码地址链接: https://pan.baidu.com/s/19DbRZLXicwMJBKfkM0HJeQ 提取码: xnf2

-----------------------------------------------------2020年4月9日14:13:05
可自行修改依赖目标框架
SuperWebSocket源码 链接: https://pan.baidu.com/s/1_brs_DL-Rx6AkLXz9KVVGA 提取码: 3rui

你可能感兴趣的:(c# SuperWebSocket服务端,html WebSocket客户端,c# WebSocket4Net 客户端 的使用)