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服务安装方法 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 编辑过 |
关键字查询
相关文章
正在查询... |