SuperSocket服务端源代码逻辑解析

SuperSocket服务端默认是以 "\r\n" (回车换行0x0D0A)作为终止符(TerminatorReceiveFilter),接收默认最多处理1024个字节【DefaultMaxRequestLength=1024】。如果一次发送超过1024的字节【发送数据中无 "\r\n"】,将抛出ProtocolError异常,并将非法的客户端连接关闭。

接收的结果StringRequestInfo对象由Key和Body通过空格字符拼接而成。

如果Body为空,则接收的实际结果就是 Key。

如果Body不为空,则接收的实际结果是 Key+" "+Body。

新建窗体应用程序TestServer,重命名窗体名为FormServer。窗体设计如下:

SuperSocket服务端源代码逻辑解析

添加对类库。SuperSocket.Common,SuperSocket.SocketBase,SuperSocket.SocketEngine,Log4Net 四个类库的引用。

测试源程序:

using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TestServer
{
    public partial class FormServer : Form
    {
        AppServer appServer = new AppServer();
        public FormServer()
        {
            InitializeComponent();
        }

        private void FormServer_Load(object sender, EventArgs e)
        {
            ServerConfig serverConfig = new ServerConfig()
            {
                Ip = "127.0.0.1",
                Port = int.Parse(txtPort.Text),
                TextEncoding = "GBK",
                MaxConnectionNumber = ServerConfig.DefaultMaxConnectionNumber,
                Mode = SocketMode.Tcp,
                MaxRequestLength = ServerConfig.DefaultMaxRequestLength,
                KeepAliveTime = ServerConfig.DefaultKeepAliveTime,
                KeepAliveInterval = ServerConfig.DefaultKeepAliveInterval,
                ListenBacklog = ServerConfig.DefaultListenBacklog,
                ReceiveBufferSize = ServerConfig.DefaultReceiveBufferSize,
                SendTimeOut = ServerConfig.DefaultSendTimeout
            };

            if (!appServer.Setup(serverConfig))
            {
                MessageBox.Show("开启监听端口失败");
                return;
            }

            if (!appServer.Start())
            {
                MessageBox.Show("服务器开启监听失败");
                return;
            }

            DisplayContent(string.Format("服务器启动监听成功,服务器IP:{0},端口:{1}...", appServer.Config.Ip, appServer.Config.Port));

            //客户端连接事件
            appServer.NewSessionConnected += AppServer_NewSessionConnected;
            //接收事件
            appServer.NewRequestReceived += AppServer_NewRequestReceived; ;
            //客户端已关闭事件
            appServer.SessionClosed += AppServer_SessionClosed; ;
        }

        private void AppServer_SessionClosed(AppSession session, SuperSocket.SocketBase.CloseReason value)
        {
            string sessionIp = string.Format("{0}:{1}", session.RemoteEndPoint.Address, session.RemoteEndPoint.Port);
            DisplayContent(string.Format("客户端已关闭:{0},端口:{1},原因:{2}", session.RemoteEndPoint.Address, session.RemoteEndPoint.Port, value));
        }

        private void AppServer_NewRequestReceived(AppSession session, SuperSocket.SocketBase.Protocol.StringRequestInfo requestInfo)
        {
            string body = requestInfo.Body;
            string charSet = session.Charset.BodyName;
            DateTime dt = session.LastActiveTime;
            string key = requestInfo.Key;//session.CurrentCommand;
            string sessionIp = string.Format("{0}:{1}", session.RemoteEndPoint.Address, session.RemoteEndPoint.Port);
            StringBuilder sb = new StringBuilder(sessionIp + ":\n接收内容:");
            string content = key;            
            if (body.Length > 0)
            {
                content = key + (" " + body);
            }
            sb.Append(content);
            sb.Append("    \n发送时间:" + dt.ToString("yyyy-MM-dd HH:mm:ss"));
            sb.Append("    \n字符编码:" + charSet);
            DisplayContent(sb.ToString());
        }

        private void AppServer_NewSessionConnected(AppSession session)
        {
            string sessionIp = string.Format("{0}:{1}", session.RemoteEndPoint.Address, session.RemoteEndPoint.Port);
            DisplayContent(string.Format("客户端已连接:{0},虚拟端口:{1}", session.RemoteEndPoint.Address, session.RemoteEndPoint.Port));
        }

        /// <summary>
        /// 异步显示内容
        /// </summary>
        /// <param name="addContent"></param>
        private void DisplayContent(string addContent)
        {
            if (this.InvokeRequired)
            {
                Action<string> actionUpd = DisplayContentEx;
                actionUpd.BeginInvoke(addContent, null, null);
            }
            else
            {
                DisplayContentEx(addContent);
            }
        }

        public void DisplayContentEx(string addContent)
        {
            this.Invoke(new MethodInvoker(() =>
            {
                if (rtxtDisplay.TextLength >= 10240)
                {
                    rtxtDisplay.Clear();
                }
                rtxtDisplay.AppendText(addContent + "\n");
                rtxtDisplay.ScrollToCaret();
            }));
        }
    }
}
程序运行如图:【新开一个客户端,建立连接,并发送】

SuperSocket服务端源代码逻辑解析

一、方法appServer.Setup(serverConfig),基本配置设置。最终的本质就是 实例化类 new AsyncSocketServer(appServer, listeners)

1.实例化类 SuperSocket.SocketEngine.SocketServerFactory,如果不指定编码格式,将默认为ASCII

         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();

2.设置监听配置:

                if (config.Port > 0)
                {
                    listeners.Add(new ListenerInfo
                    {
                        EndPoint = new IPEndPoint(ParseIPAddress(config.Ip), config.Port),
                        BackLog = config.ListenBacklog,
                        Security = BasicSecurity
                    });
                }

3.设置接收过滤:

return new CommandLineReceiveFilterFactory(TextEncoding);

=>new CommandLineReceiveFilterFactory(encoding, new BasicRequestInfoParser());

=>new TerminatorReceiveFilterFactory("\r\n",encoding, new BasicRequestInfoParser());

//注意:这里指定 终止符为 回车换行。

4.创建socket服务,最终目的就是实例化类:AsyncSocketServer

CreateSocketServer<TRequestInfo>(IAppServer appServer, ListenerInfo[] listeners, IServerConfig config)

=> case(SocketMode.Tcp):
                    return new AsyncSocketServer(appServer, listeners);

 

二、方法:appServer.Start()。启动一个服务端实例。监听

=>AsyncSocketServer 对象m_SocketServer.Start()

实例化最大连接数【MaxConnectionNumber】个异步socket代理对象:SocketAsyncEventArgsProxy

new SocketAsyncEventArgsProxy(SocketAsyncEventArgs socketEventArgs,true);

并订阅 【完成异步操作】的事件 Completed

public SocketAsyncEventArgsProxy(SocketAsyncEventArgs socketEventArgs, bool isRecyclable)
        {
            SocketEventArgs = socketEventArgs;
            OrigOffset = socketEventArgs.Offset;
            SocketEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(SocketEventArgs_Completed);
            IsRecyclable = isRecyclable;
        }

        static void SocketEventArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            var socketSession = e.UserToken as IAsyncSocketSession;

            if (socketSession == null)
                return;

            if (e.LastOperation == SocketAsyncOperation.Receive)
            {
                socketSession.AsyncRun(() => socketSession.ProcessReceive(e));
            }
            else
            {
                throw new ArgumentException("The last operation completed on the socket was not a receive");
            }
        } 

2.执行父类的启动监听:抽象类SocketServerBase的Start()方法

 

内部类 TcpAsyncSocketListener的Start()方法

var listener => return new TcpAsyncSocketListener(listenerInfo);

                var listener = CreateListener(ListenerInfos[i]);
                listener.Error += new ErrorHandler(OnListenerError);
                listener.Stopped += new EventHandler(OnListenerStopped);

                //当接受Accept一个客户端时触发
                listener.NewClientAccepted += new NewClientAcceptHandler(OnNewClientAccepted);

3.执行异步监听类TcpAsyncSocketListener的Start(Config)方法,这才是真正的启用监听。

public override bool Start(IServerConfig config)
        {
            m_ListenSocket = new Socket(this.Info.EndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                m_ListenSocket.Bind(this.Info.EndPoint);
                m_ListenSocket.Listen(m_ListenBackLog);

                m_ListenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                m_ListenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);

                SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
                m_AcceptSAE = acceptEventArg;
                acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(acceptEventArg_Completed);

                if (!m_ListenSocket.AcceptAsync(acceptEventArg))
                    ProcessAccept(acceptEventArg);

                return true;

            }
            catch (Exception e)
            {
                OnError(e);
                return false;
            }
        }

4.等待一个新的客户端连接:

开始一个异步操作以接受传入的连接尝试。

m_ListenSocket.AcceptAsync(acceptEventArg)

当一个客户端连接成功时,会触发完成事件:

void ProcessAccept(SocketAsyncEventArgs e)

生成一个用于发送和接收的Socket对象

socket = e.AcceptSocket;

if (socket != null)
                OnNewClientAccepted(socket, null);

自动触发事件:AsyncSocketServer类的

protected override void OnNewClientAccepted(ISocketListener listener, Socket client, object state)