.net 用supersocket搭建socket server

背景:.NET新项目想用supersocket来代替之前的socket来搭建服务端,一个原因是早听说这个框架开源、可用性挺高,一个原因是之前写的服务总是在内存、可读性上有问题,借此来使用并学习。

现在先记录一下简单使用过程。

supersocket官网:https://docs.supersocket.net/   github地址:https://github.com/kerryjiang/SuperSocket

SuperSocket 对象模型图示意图(引自官网)

SuperSocket 请求处理模型示意图

SuperSocket Request Handling Model

在supersocket中,一个appserver代表一个server,一个appssion代表一个客户端连接,receivefilter是过滤器,这里将接收到的字节流进行处理并转换成实体类,command是命令类,用来接收数据后根据数据进行相应的业务处理。

下边按一个自定义的协议例子来搭建socket

1.首先新建项目,安装SuperSocket

2.自定义请求类,需继承接口IRequestInfo

   /// /// 自定义请求/// public class MyRequestInfo: IRequestInfo{public MyRequestInfo(string method,long timestamp,string ip,string mac,string version){this.method = method;this.timestamp = timestamp;this.ip = ip;this.mac = mac;this.version = version;}public string Key { get; set; }public string method { get; set; }public long timestamp { get; set; }public string ip { get; set; }public string mac { get; set; }public string version { get; set; }public override string ToString(){return string.Format("{{'method': '{0}','timestamp': {1},'body': {{'ip': '{2}','mac': '{3}','time': {1},'version': '{4}'}}}}", method,timestamp,ip,mac,version);}}

这里,Key字段必须实现,其他字段是我的这个例子中的属性

3.搭建过滤器,继承接口ReceiveFilterBase

 public class MyReceiveFilter: ReceiveFilterBase{private SearchMarkState m_BeginSearchState;//开始标记private SearchMarkState m_EndSearchState;//结束标记private bool m_FoundBegin = false;protected MyRequestInfo NullRequestInfo = default(MyRequestInfo);public int LeftBufferSize { get; }public IReceiveFilter NextReceiveFilter { get; }public FilterState State { get; }public override MyRequestInfo Filter(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest){rest = 0;int searchEndMarkOffset;int searchEndMarkLength;//在此处做了处理,将接收到的第一个字符作为起始过滤标志,到结束。返回指定长度的数据。byte[] startMark = new byte[] { readBuffer[offset] };byte[] endMark = new byte[] { readBuffer[offset + length - 1] };//最后一个字符byte[] endMark1 = new byte[1] { 0x7d };//}if (startMark[0]==0x7b)//起始是{,完整请求{//TODO 处理接收到的数据,判断是否完整一条请求return YouRequestInfo;}else{return NullRequestInfo;//不完整请求}}public void Reset(){m_BeginSearchState.Matched = 0;m_EndSearchState.Matched = 0;m_FoundBegin = false;//base.Reset();}}

借用官网,这儿有很多种情况需要你处理:

  • 当你在接收缓冲区中找到一条完整的请求时,你必须返回一个你的请求类型的实例.
  • 当你在接收缓冲区中没有找到一个完整的请求时, 你需要返回 NULL.
  • 当你在接收缓冲区中找到一条完整的请求, 但接收到的数据并不仅仅包含一个请求时,设置剩余数据的长度到输出变量 "rest". SuperSocket 将会检查这个输出参数 "rest", 如果它大于 0, 此 Filter 方法 将会被再次执行, 参数 "offset" 和 "length" 会被调整为合适的值

4.编写你的AppServer(继承AppServer)、Appssion(继承Appssion)

public class MyAppServer:AppServer{public MyAppServer():base(new DefaultReceiveFilterFactory()){}protected void NewSessionConnected(MySession session){base.OnNewSessionConnected(session);}}
public class MySession:AppSession{protected override void HandleException(Exception e){base.HandleException(e);}protected override void OnSessionStarted(){base.OnSessionStarted();}protected override int GetMaxRequestLength(){return base.GetMaxRequestLength();}protected override void HandleUnknownRequest(MyRequestInfo requestInfo){base.HandleUnknownRequest(requestInfo);}}

自定义然后在主程序使用

5.正式使用

 MyAppServer appServer;string ipAddress_Connect;string ipAddress_Close;string ipAddress_Receive;
//存储session和对应ip端口号的泛型集合Dictionary sessionList = new Dictionary();
static void Main(){appServer = new MyAppServer();if (!appServer.Setup(int.Parse(ServerPort))){Console.WriteLine("Failed to Setup");return;}if (!appServer.Start()){Console.WriteLine("Failed to Start");return;}else{AddMsg("开启监听,端口:" + ServerPort);}//SuperSocket自定义了三个事件 ,连接事件,接收事件,关闭事件appServer.NewSessionConnected += appServer_NewSessionConnected;appServer.NewRequestReceived += appServer_NewRequestReceived;appServer.SessionClosed += appServer_SessionClosed;}/// /// 接收连接/// /// static void appServer_NewSessionConnected(MySession session){//有新连接的时候,添加记录  session.LocalEndPoint属性获取当前session的ip和端口号//AppSession 代表一个和客户端的逻辑连接,基于连接的操作应该定于在该类之中。你可以用该类的实例发送数据到客户端,接收客户端发送的数据或者关闭连接。//获取远程客户端的ip端口号ipAddress_Connect = session.RemoteEndPoint.ToString();sessionList.Add(ipAddress_Connect, session);Console.WriteLine(ipAddress_Connect + "已连接!");}/// /// 接收数据/// /// /// static void appServer_NewRequestReceived(MySession session, MyRequestInfo requestInfo){string msg = requestInfo.ToString();Console.WriteLine($"收到{ipAddress_Receive}数据:{msg}");}/// /// 关闭连接/// /// /// static void appServer_SessionClosed(MySession session, SuperSocket.SocketBase.CloseReason value){ipAddress_Close = session.RemoteEndPoint.ToString();sessionList.Remove(ipAddress_Close);Console.WriteLine(ipAddress_Close + "已关闭连接!");}

启动。

这里还没用到命令,看个人情况使用吧。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部