SuperSocket服务端源代码逻辑解析
SuperSocket服务端默认是以 "\r\n" (回车换行0x0D0A)作为终止符(TerminatorReceiveFilter),接收默认最多处理1024个字节【DefaultMaxRequestLength=1024】。如果一次发送超过1024的字节【发送数据中无 "\r\n"】,将抛出ProtocolError异常,并将非法的客户端连接关闭。
接收的结果StringRequestInfo对象由Key和Body通过空格字符拼接而成。
如果Body为空,则接收的实际结果就是 Key。
如果Body不为空,则接收的实际结果是 Key+" "+Body。
新建窗体应用程序TestServer,重命名窗体名为FormServer。窗体设计如下:
添加对类库。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();
}));
}
}
}
程序运行如图:【新开一个客户端,建立连接,并发送】
一、方法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)