博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SupperSocket深入浅出(一)
阅读量:5272 次
发布时间:2019-06-14

本文共 19186 字,大约阅读时间需要 63 分钟。

  花了几天时间了解了SupperSocket工作原理,各各类之间的工作关系。SupperSocket大部资料网上都有,但写的都不适合初学者。

今天花点时间写下这几天的学习成果,一方面是为了将来更好的回顾知识点,另一方面想给初学者提供一份参考资料。考虑到笔功有限,

如果下面有什么信息不正确或写的不好,请大家多多包容!

 

  首先我贴一简单的代码。后面我会详细的说明工作原理和他们之间如何调用!下面的代码我也是从网上找的,相当简单。

我今天主要是讲解下SupperSocket的理解!

public class TelnetServer : AppServer
{ protected override bool Setup(IRootConfig rootConfig, IServerConfig config) { return base.Setup(rootConfig, config); } protected override void OnStartup() { base.OnStartup(); } protected override void OnStopped() { base.OnStopped(); } }
public class TelnetSession : AppSession
{ protected override void OnSessionStarted() { //this.Send("Welcome to SuperSocket Telnet Server\r\n"); byte[] bytes = Encoding.ASCII.GetBytes("Welcome\r\n to SuperSocket\r\n Telnet Server\r\n"); this.Send(bytes, 0, bytes.Length); } protected override void HandleUnknownRequest(StringRequestInfo requestInfo) { this.Send("Unknow request"); } protected override void HandleException(Exception e) { this.Send("Application error: {0}", e.Message); } protected override void OnSessionClosed(CloseReason reason) { //add you logics which will be executed after the session is closed base.OnSessionClosed(reason); } }
public class ECHO : CommandBase
{ public override void ExecuteCommand(TelnetSession session, StringRequestInfo requestInfo) { session.Send(requestInfo.Body); } }
static void Main(string[] args)        {            Console.WriteLine("Press any key to start the server!");            Console.ReadKey();            Console.WriteLine();            var appServer = new TelnetServer();            //Setup the appServer            if (!appServer.Setup(2012)) //Setup with listening port            {                Console.WriteLine("Failed to setup!");                Console.ReadKey();                return;            }            Console.WriteLine();            //Try to start the appServer            if (!appServer.Start())            {                Console.WriteLine("Failed to start!");                Console.ReadKey();                return;            }            Console.WriteLine("The server started successfully, press key 'q' to stop it!");            while (Console.ReadKey().KeyChar != 'q')            {                Console.WriteLine();                continue;            }            //Stop the appServer            appServer.Stop();            Console.WriteLine("The server was stopped!");            Console.ReadKey();        }

服务端代码就上面四部分,看起来很简单吧,但是大家真的看懂了吗,他们的工作原理是怎样的。命令 ECHO 这个类根本没有构造对象,他是怎样运行的?你越看越疑惑吧!

后面我会说明。

我还是先把客户端代码贴出来。代码简化了,如果大家不知道EasyClietn 可以使用Nuget搜索SuperSocket.ClientEngine、SuperSocket.ProtoBase 

因为版本有很多,大家最好是用Nuget

 

private void button1_Click(object sender, EventArgs e)        {            string strText = "add 1 1\r\n";            if (client != null && client.IsConnected  )            {                Byte[] smk = new Byte[strText.Length];                for (int i = 0; i < strText.Length; i++)                {                    Byte ss = Convert.ToByte(strText[i]);                    smk[i] = ss;                }                byte[] b = Encoding.ASCII.GetBytes("ECHO 1 1\r\n");                client.Send(smk.ToArray());  //EasyClient
client } }

 

 

byte[] b = Encoding.ASCII.GetBytes("ECHO 1 1\r\n"); client.Send(smk.ToArray());  给服务端发送了二进制的“ECHO 1 1\r\n"  ,在这里给大家一个问题,为什么后面要加\r\n 换行符。大家带着问题继续往下看。 现在给了大家两个问题?,现在我们来解决问题。 服务端是如何接收到消息。其它大家可以不要具体体解,因为SupperStocket封闭了TCP 和 UDP 层。 SuperSocket.SocketEngine.AsyncStreamSocketSession 这个类是工作最底运类

从这个类可以知道数据的接收来源。 

这个类是由

SuperSocket.SocketEngine.AsyncStreamSocketSession 《 SuperSocket.SocketEngine.AsyncSocketServer 《 SocketServerFactory 《 ProviderKey

《 ProviderFactoryInfo 《 AppDomainAppServer 《 DefaultBootstrap

这是最底层类,获取数据和发达送数据,这个大部分我们不要了解,因为这些都被AppSession封装起来了。 
 

 大家想了解的可以看下这个类。

class AsyncStreamSocketSession : SocketSession, IAsyncSocketSessionBase, INegotiateSocketSession    {        private byte[] m_ReadBuffer;        private int m_Offset;        private int m_Length;        private bool m_IsReset;        public AsyncStreamSocketSession(Socket client, SslProtocols security, SocketAsyncEventArgsProxy socketAsyncProxy)            : this(client, security, socketAsyncProxy, false)        {        }        public AsyncStreamSocketSession(Socket client, SslProtocols security, SocketAsyncEventArgsProxy socketAsyncProxy, bool isReset)            : base(client)        {            SecureProtocol = security;            SocketAsyncProxy = socketAsyncProxy;            var e = socketAsyncProxy.SocketEventArgs;            m_ReadBuffer = e.Buffer;            m_Offset = e.Offset;            m_Length = e.Count;            m_IsReset = isReset;        }        ///         /// Starts this session communication.        ///         public override void Start()        {            //Hasn't started, but already closed            if (IsClosed)                return;            OnSessionStarting();        }        private void OnSessionStarting()        {            try            {                OnReceiveStarted();                m_Stream.BeginRead(m_ReadBuffer, m_Offset, m_Length, OnStreamEndRead, m_Stream);            }            catch (Exception e)            {                LogError(e);                OnReceiveTerminated(CloseReason.SocketError);                return;            }            if (!m_IsReset)                StartSession();        }        private void OnStreamEndRead(IAsyncResult result)        {            var stream = result.AsyncState as Stream;            int thisRead = 0;            try            {                thisRead = stream.EndRead(result);            }            catch (Exception e)            {                LogError(e);                OnReceiveTerminated(CloseReason.SocketError);                return;            }            if (thisRead <= 0)            {                OnReceiveTerminated(CloseReason.ClientClosing);                return;            }            OnReceiveEnded();            int offsetDelta;            try            {                offsetDelta = AppSession.ProcessRequest(m_ReadBuffer, m_Offset, thisRead, true);            }            catch (Exception ex)            {                LogError("Protocol error", ex);                this.Close(CloseReason.ProtocolError);                return;            }            try            {                if (offsetDelta < 0 || offsetDelta >= Config.ReceiveBufferSize)                    throw new ArgumentException(string.Format("Illigal offsetDelta: {0}", offsetDelta), "offsetDelta");                m_Offset = SocketAsyncProxy.OrigOffset + offsetDelta;                m_Length = Config.ReceiveBufferSize - offsetDelta;                OnReceiveStarted();                m_Stream.BeginRead(m_ReadBuffer, m_Offset, m_Length, OnStreamEndRead, m_Stream);            }            catch (Exception exc)            {                LogError(exc);                OnReceiveTerminated(CloseReason.SocketError);                return;            }        }        private Stream m_Stream;        private SslStream CreateSslStream(ICertificateConfig certConfig)        {            //Enable client certificate function only if ClientCertificateRequired is true in the configuration            if(!certConfig.ClientCertificateRequired)                return new SslStream(new NetworkStream(Client), false);            //Subscribe the client validation callback            return new SslStream(new NetworkStream(Client), false, ValidateClientCertificate);        }        private bool ValidateClientCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)        {            var session = AppSession;            //Invoke the AppServer's method ValidateClientCertificate            var clientCertificateValidator = session.AppServer as IRemoteCertificateValidator;            if (clientCertificateValidator != null)                return clientCertificateValidator.Validate(session, sender, certificate, chain, sslPolicyErrors);            //Return the native validation result            return sslPolicyErrors == SslPolicyErrors.None;        }        private IAsyncResult BeginInitStream(AsyncCallback asyncCallback)        {            IAsyncResult result = null;            var certConfig = AppSession.Config.Certificate;            var secureProtocol = SecureProtocol;            switch (secureProtocol)            {                case (SslProtocols.None):                    m_Stream = new NetworkStream(Client);                    break;                case (SslProtocols.Default):                case (SslProtocols.Tls):                case (SslProtocols.Ssl3):                    SslStream sslStream = CreateSslStream(certConfig);                    result = sslStream.BeginAuthenticateAsServer(AppSession.AppServer.Certificate, certConfig.ClientCertificateRequired, SslProtocols.Default, false, asyncCallback, sslStream);                    break;                case (SslProtocols.Ssl2):                    SslStream ssl2Stream = CreateSslStream(certConfig);                    result = ssl2Stream.BeginAuthenticateAsServer(AppSession.AppServer.Certificate, certConfig.ClientCertificateRequired, SslProtocols.Ssl2, false, asyncCallback, ssl2Stream);                    break;                default:                    var unknownSslStream = CreateSslStream(certConfig);                    result = unknownSslStream.BeginAuthenticateAsServer(AppSession.AppServer.Certificate, certConfig.ClientCertificateRequired, secureProtocol, false, asyncCallback, unknownSslStream);                    break;            }            return result;        }        private void OnBeginInitStreamOnSessionConnected(IAsyncResult result)        {            OnBeginInitStream(result, true);        }        private void OnBeginInitStream(IAsyncResult result)        {            OnBeginInitStream(result, false);        }        private void OnBeginInitStream(IAsyncResult result, bool connect)        {            var sslStream = result.AsyncState as SslStream;            try            {                sslStream.EndAuthenticateAsServer(result);            }            catch (IOException exc)            {                LogError(exc);                if (!connect)//Session was already registered                    this.Close(CloseReason.SocketError);                OnNegotiateCompleted(false);                return;            }            catch (Exception e)            {                LogError(e);                if (!connect)//Session was already registered                    this.Close(CloseReason.SocketError);                OnNegotiateCompleted(false);                return;            }            m_Stream = sslStream;            OnNegotiateCompleted(true);        }        protected override void SendSync(SendingQueue queue)        {            try            {                for (var i = 0; i < queue.Count; i++)                {                    var item = queue[i];                    m_Stream.Write(item.Array, item.Offset, item.Count);                }                OnSendingCompleted(queue);            }            catch (Exception e)            {                LogError(e);                OnSendError(queue, CloseReason.SocketError);                return;            }        }        protected override void OnSendingCompleted(SendingQueue queue)        {            try            {                m_Stream.Flush();            }            catch (Exception e)            {                LogError(e);                OnSendError(queue, CloseReason.SocketError);                return;            }            base.OnSendingCompleted(queue);        }        protected override void SendAsync(SendingQueue queue)        {            try            {                var item = queue[queue.Position];                m_Stream.BeginWrite(item.Array, item.Offset, item.Count, OnEndWrite, queue);            }            catch (Exception e)            {                LogError(e);                OnSendError(queue, CloseReason.SocketError);            }        }        private void OnEndWrite(IAsyncResult result)        {            var queue = result.AsyncState as SendingQueue;            try            {                m_Stream.EndWrite(result);            }            catch (Exception e)            {                LogError(e);                OnSendError(queue, CloseReason.SocketError);                return;            }                        var nextPos = queue.Position + 1;            //Has more data to send            if (nextPos < queue.Count)            {                queue.Position = nextPos;                SendAsync(queue);                return;            }            OnSendingCompleted(queue);        }        public override void ApplySecureProtocol()        {            var asyncResult = BeginInitStream(OnBeginInitStream);            if (asyncResult != null)                asyncResult.AsyncWaitHandle.WaitOne();        }        public SocketAsyncEventArgsProxy SocketAsyncProxy { get; private set; }        ILog ILoggerProvider.Logger        {            get { return AppSession.Logger; }        }        public override int OrigReceiveOffset        {            get { return SocketAsyncProxy.OrigOffset; }        }        private bool m_NegotiateResult = false;        void INegotiateSocketSession.Negotiate()        {            IAsyncResult asyncResult;            try            {                asyncResult = BeginInitStream(OnBeginInitStreamOnSessionConnected);            }            catch (Exception e)            {                LogError(e);                OnNegotiateCompleted(false);                return;            }            if (asyncResult == null)            {                OnNegotiateCompleted(true);                return;            }        }        bool INegotiateSocketSession.Result        {            get { return m_NegotiateResult; }        }        private EventHandler m_NegotiateCompleted;        event EventHandler INegotiateSocketSession.NegotiateCompleted        {            add { m_NegotiateCompleted += value; }            remove { m_NegotiateCompleted -= value; }        }        private void OnNegotiateCompleted(bool negotiateResult)        {            m_NegotiateResult = negotiateResult;            //One time event handler            var handler = Interlocked.Exchange
(ref m_NegotiateCompleted, null); if (handler == null) return; handler(this, EventArgs.Empty); } }
View Code

 

SuperSocket.SocketEngine.AsyncStreamSocketSession 《 SuperSocket.SocketEngine.AsyncSocketServer 《 SocketServerFactory 《 AppServerBase 在SuperSocket.SocketBase.AppServerBase类里
private bool SetupSocketServer()        {            try            {                m_SocketServer = m_SocketServerFactory.CreateSocketServer
(this, m_Listeners, Config); return m_SocketServer != null; } catch (Exception e) { if (Logger.IsErrorEnabled) Logger.Error(e); return false; } }
 

 

 
#region IActiveConnector        ///         /// Connect the remote endpoint actively.        ///         /// The target end point.        /// The local end point.        /// 
///
This server cannot support active connect.
Task
IActiveConnector.ActiveConnect(EndPoint targetEndPoint, EndPoint localEndPoint) { var activeConnector = m_SocketServer as IActiveConnector; if (activeConnector == null) throw new Exception("This server cannot support active connect."); return activeConnector.ActiveConnect(targetEndPoint, localEndPoint); } ///
/// Connect the remote endpoint actively. /// ///
The target end point. ///
///
This server cannot support active connect.
Task
IActiveConnector.ActiveConnect(EndPoint targetEndPoint) { return ((IActiveConnector)this).ActiveConnect(targetEndPoint, null); } #endregion IActiveConnector
 
private bool SetupSocketServer()        {            try            {                m_SocketServer = m_SocketServerFactory.CreateSocketServer
(this, m_Listeners, Config); return m_SocketServer != null; } catch (Exception e) { if (Logger.IsErrorEnabled) Logger.Error(e); return false; } }
private void SetupBasic(IRootConfig rootConfig, IServerConfig config, ISocketServerFactory socketServerFactory)        {            if (rootConfig == null)                throw new ArgumentNullException("rootConfig");            RootConfig = rootConfig;            if (config == null)                throw new ArgumentNullException("config");            if (!string.IsNullOrEmpty(config.Name))                m_Name = config.Name;            else                m_Name = string.Format("{0}-{1}", this.GetType().Name, Math.Abs(this.GetHashCode()));            Config = config;            SetDefaultCulture(rootConfig, config);            if (!m_ThreadPoolConfigured)            {                if (!TheadPoolEx.ResetThreadPool(rootConfig.MaxWorkingThreads >= 0 ? rootConfig.MaxWorkingThreads : new Nullable
(), rootConfig.MaxCompletionPortThreads >= 0 ? rootConfig.MaxCompletionPortThreads : new Nullable
(), rootConfig.MinWorkingThreads >= 0 ? rootConfig.MinWorkingThreads : new Nullable
(), rootConfig.MinCompletionPortThreads >= 0 ? rootConfig.MinCompletionPortThreads : new Nullable
())) { throw new Exception("Failed to configure thread pool!"); } m_ThreadPoolConfigured = true; } if (socketServerFactory == null) { var socketServerFactoryType = Type.GetType("SuperSocket.SocketEngine.SocketServerFactory, SuperSocket.SocketEngine", true); socketServerFactory = (ISocketServerFactory)Activator.CreateInstance(socketServerFactoryType); } m_SocketServerFactory = socketServerFactory; //Read text encoding from the configuration if (!string.IsNullOrEmpty(config.TextEncoding)) TextEncoding = Encoding.GetEncoding(config.TextEncoding); else TextEncoding = new ASCIIEncoding(); }

 

 

请天就写到这里了,看到这里你可以结合源码应该能知道SuperSocket是如何发送数据和接收数据。当前接收的数据还是停留在 TCP UDP层面上。下一稿将说明应用动,协议和命令是怎样工作。
 

 

转载于:https://www.cnblogs.com/qq247039968/p/7837869.html

你可能感兴趣的文章
python05
查看>>
spring ioc 源码解析
查看>>
自定制横向ListView资料分享
查看>>
LVM(扩展)
查看>>
bzoj5492:[Hnoi2019]校园旅行
查看>>
机器学习的5种“兵法"
查看>>
最近两个月累啊
查看>>
微信小程序使用字体图标的方法
查看>>
shell脚本
查看>>
D - Bomb
查看>>
题解:城南树林。
查看>>
hadoop 使用java操作hdfs
查看>>
中年男人 中年女人 中年人
查看>>
GoFramework框架简介(三)通信机制篇
查看>>
python全栈学习--day31(正则)
查看>>
h.264语法结构分析
查看>>
基督-神[上帝]的道,真理的本真归回
查看>>
https请求抛出异常
查看>>
chrome浏览器更换favicon.ico后不更新缓存解决方案
查看>>
面试试题 一 (排列组合)
查看>>