LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

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

admin
2019年11月12日 17:33 本文热度 4898
c# superwebsocket服务端可以寄宿在控制台程序、窗体程序、Windows服务
c# websocket客户端可以是控制台程序、窗体程序、Windows服务、html、手机,能连上websocket的就行了
服务端可以开启wss安全链接

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

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

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

底部有源代码百度盘下载,Windows服务安装方法

1.服务端
把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<WebSocketSession, string> MessageReceived;
        public event Action<WebSocketSession> NewConnected;
        public event Action<WebSocketSession> Closed;
        #endregion

        public WebSocketServer WebSocket;

        Thread _thread;
        bool _isRunning = true;


        public WSocketServer()
        {
        }

        #region WebSockertServer
        /// <summary>
        /// 开启服务端
        /// </summary>
        /// <param name="port"></param>
        /// <param name="serverName"></param>
        /// <param name="isUseCertificate"></param>
        /// <param name="serverStoreName"></param>
        /// <param name="serverSecurity"></param>
        /// <param name="serverThumbprint"></param>
        /// <returns></returns>
        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;
        }
        /// <summary>
        /// 消息触发事件
        /// </summary>
        /// <param name="session"></param>
        /// <param name="value"></param>
        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());
            }
        }
        /// <summary>
        /// 新链接触发事件
        /// </summary>
        /// <param name="session"></param>
        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());
            }
        }
        /// <summary>
        /// 客户端链接关闭触发事件
        /// </summary>
        /// <param name="session"></param>
        /// <param name="value"></param>
        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
        /// <summary>
        /// 关闭服务端触发事件
        /// </summary>
        public void Dispose()
        {
            this._isRunning = false;
            foreach (WebSocketSession session in this.WebSocket.GetAllSessions())
            {
                session.Close();
            }
            try
            {
                this.WebSocket.Stop();
            }
            catch { }
        }
        /// <summary>
        /// 输出实时连接线程
        /// </summary>
        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);
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="session">客户端连接</param>
        /// <param name="message">消息内容</param>

        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

然后写个业务逻辑类,操作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# websocket 服务端搭建完成了

因为这里是通过控制台来调用调试这个服务,所以要再建一个控制台项目

然后选中控制台项目,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<string> MessageReceived;
        #endregion

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

        #region "web socket "
        /// <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) 
            {
                _Logger.Error(ex.ToString());
                result = false;
            }
            return result;
        }
        /// <summary>
        /// 消息收到事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void WebSocket_MessageReceived(object sender, MessageReceivedEventArgs e) 
        {
            _Logger.Info(" Received:" +e.Message);
            MessageReceived?.Invoke(e.Message);
        }
        /// <summary>
        /// Socket关闭事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void WebSocket_Closed(object sender, EventArgs e) 
        {
            _Logger.Info("websocket_Closed");
        }
        /// <summary>
        /// Socket报错事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void WebSocket_Error(object sender, ErrorEventArgs e) 
        {
            _Logger.Info("websocket_Error:" + e.Exception.ToString());
        }
        /// <summary>
        /// Socket打开事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void WebSocket_Opened(object sender, EventArgs e) 
        {
            _Logger.Info(" websocket_Opened");         
        }
        /// <summary>
        /// 检查重连线程
        /// </summary>
        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

        /// <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()
        {
            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

装完就可以开始连接服务端了

3.客户端-网页

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
<div id="onMessage" style="width:100%;height:200px;overflow-y:scroll;">

</div>
<input type="text" id="input" /><input id="sendMessage" type="button" value="发送" />
</body>
</html>
<script>
    //websocket 类
    var myWS = function () {
        this.ws = null;
        this.url = null;
        this.onmessage = function () { };
        this.onopen = function () {
        };
        this.onclose = function () { };
        this.onerror = function () {
        };
    };
    myWS.prototype.sendMessage = function (message) {//客戶端發送消息到服務器方法
        if (this.ws != null && this.ws.readyState == 1) {
            this.ws.send(message);
        }
    };
    myWS.prototype.start = function () {//啟動鏈接
        this.connect();
        this.conncheckstatus();
        this.heartbeat();
    };
    //心跳
    myWS.prototype.heartbeat = function () {
        var obj = this;
        setTimeout(function () {
            if (obj.ws != null && obj.ws.readyState == 1) {
                var message = "IsHere**";
                obj.ws.send(message);
            }
            setTimeout(arguments.callee, 300000);
        }, 10);
    };
    myWS.prototype.conncheckstatus = function () {
        var obj = this;
        setTimeout(function () {
            if (obj.ws != null && obj.ws.readyState != 0 && obj.ws.readyState != 1) {
                obj.connect();
            }
            setTimeout(arguments.callee, 5000);
        }, 15);
    };
    myWS.prototype.connect = function () {
        this.disconnect();
        //WebSocket地址
        if (this.url != null && this.url != "") {
            try {
                if ("WebSocket" in window) {
                    this.ws = new WebSocket(this.url);
                }
                else if ("MozWebSocket" in window) {
                    this.ws = new MozWebSocket(this.url);
                }
                else {
                    alert("browser not support websocket");
                }
                if (this.ws != null) {
                    var that = this;
                    this.ws.onopen = function (event) { that.onopen(event); };
                    this.ws.onmessage = function (event) { that.onmessage(event); };
                    this.ws.onclose = function (event) { that.onclose(event); };
                    this.ws.onerror = function (event) { that.onerror(event); };
                }
            }
            catch (ex) {
                console.log("connect:" + ex);
            }
        }
    };
    myWS.prototype.disconnect = function () {
        if (this.ws != null) {
            try {
                this.ws.close();
                this.ws = null;
            }
            catch (ex) {
                this.ws = null;
            }
        }
    };
</script>

<script>
    var _ws = new myWS();
    _ws.url = ''ws://192.168.1.13:1234/lcj网页'';
    //注册接收服务端消息的方法 服务端数据位于event.data字段
    _ws.onmessage = (event) => {
        document.getElementById(''onMessage'').innerHTML += event.data + ''<br/>'';
        document.getElementById(''onMessage'').scrollTop = document.getElementById(''onMessage'').scrollHeight;
    };
    //启动链接
    _ws.start();

    document.getElementById(''sendMessage'').addEventListener(''click'', () => {
        //客户端发送消息到服务端
        _ws.sendMessage(document.getElementById(''input'').value);
        document.getElementById(''input'').value = '''';
    });
</script>
完成…
源代码下载下载

Windows服务安装方法
1.把项目模式改成发布模式Release
2.右键项目生成或者重新生成
3.打开项目位置,打开bin文件夹,打开Release文件夹

4.把服务必备的一些组件都复制走


安装完成,在计算机管理-服务里面可以看到,你的服务名字,还没启动,需要手动开启,或者电脑重启后自动开启

右键服务-选择第一个“启动”

卸载服务,先打开服务管理,右键,停止,然后复制删除命令到cmd执行

刷新一下服务列表,服务已经删除

如果想要更新服务的话,要先停止服务,然后把生成后的新dll啊或者exe,覆盖掉旧的就可以了,修改配置文件的话也需要重新启动服务才能生效,停止服务需要一点时间,不能一点停止就立即覆盖,系统会报文件占用

所有步骤都完成了

这里是安装服务的工具和命令
链接:下载

WSS 开启介绍

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


/// <summary>
        /// 开启服务端
        /// </summary>
        /// <param name="port">123</param>
        /// <param name="serverName">test</param>
        /// <param name="isUseCertificate">true 如果开启wss需要用域名访问(wss:\\abc.com:123\)</param>
        /// <param name="certificateStoreName">My -证书安装后的存储位置(一般是“个人”)</param>
        /// <param name="security">ssl/tls</param>
        /// <param name="certificateThumbprint">‎7384a6027fa8004585c0958c7fcbcb8fd9cd27fb 证书指纹 如果指纹填空,则使用路径加载证书,否则使用指纹</param>
        /// <param name="certificatePath">D:\1774183_xxx_iis\1774183_xxx.pfx 证书所在路径</param>
        /// <param name="certificatePwd">ABC 证书密码</param>
        /// <returns></returns>
        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;
        }
这里我使用配置文件

源码地址链接:下载

该文章在 2019/11/12 17:33:27 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved