.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

   /// <summary>
    /// 自定义请求
    /// </summary>
    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<MyRequestInfo>
    {
        private SearchMarkState<byte> m_BeginSearchState;//开始标记
        private SearchMarkState<byte> m_EndSearchState;//结束标记
        private bool m_FoundBegin = false;
        protected MyRequestInfo NullRequestInfo = default(MyRequestInfo);
        public int LeftBufferSize { get; }

        public IReceiveFilter<MyRequestInfo> 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<MySession,MyRequestInfo>
    {
        public MyAppServer():base(new DefaultReceiveFilterFactory<MyReceiveFilter, MyRequestInfo>())
        {

        }

        protected void NewSessionConnected(MySession session)
        {
            base.OnNewSessionConnected(session);
        }
    }
public class MySession:AppSession<MySession,MyRequestInfo>
    {
        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<string, MySession> sessionList = new Dictionary<string, MySession>();
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;
        }

 /// <summary>
        /// 接收连接
        /// </summary>
        /// <param name="session"></param>
        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 + "已连接!");
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="session"></param>
        /// <param name="requestInfo"></param>
        static void appServer_NewRequestReceived(MySession session, MyRequestInfo requestInfo)
        {

            string msg = requestInfo.ToString();
            Console.WriteLine($"收到{ipAddress_Receive}数据:{msg}");
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <param name="session"></param>
        /// <param name="value"></param>
        static void appServer_SessionClosed(MySession session, SuperSocket.SocketBase.CloseReason value)
        {
            ipAddress_Close = session.RemoteEndPoint.ToString();
            sessionList.Remove(ipAddress_Close);
            Console.WriteLine(ipAddress_Close + "已关闭连接!");
        }

启动。

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

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SuperSocket 是一个轻量级, 跨平台而且可扩展的 .Net/Mono Socket 服务器程序框架。你无须了解如何使用 Socket, 如何维护 Socket 连接和 Socket 如何工作,但是你却可以使用 SuperSocket 很容易的开发出一款 Socket 服务器端软件,例如游戏服务器,GPS 服务器, 工业控制服务和数据采集服务器等等。 SuperSocket具有如下特点: 高性能的事件驱动通信; 非常简单易用; 你只需要通过创建几个类就能获得一个健壮的 Socket 服务器; 内置的命令行协议让你能够迅速创建一个网络命令行接口服务器; 强大且高性能的协议解析实现工具帮你简化了网络数据的分析工作; 灵活的配置功能和友好的配置 API; 多监听器支持; 让你在一个服务器实例内监听多个端口; 多服务器实例托管的支持让你从容面对复杂的部署需求; 应用程序域和进程级别的隔离能够满足你大部分的宿主场景; 内置的 SSL/TLS 加密支持; 会话级别的发送队列能够让你通过会话并发的发送数据,并保持高性能和可控性; SuperSocket 的命令处理模式让你的业务逻辑更清晰,更有条理; 优良的可扩展 API 支持: Command Filter, Connection Filter, Command Loader; 可替换的日志架构允许你使用你喜欢的日志组件; 动态语言的支持; 允许你用 Python 之类的脚本语言来实现命令; 与 Mono/Linux 保持二进制级别的兼容; Windows Azure 的支持; 内置你可以直接用于 Flash 或 Silverlight 客户端的 Socket 策略服务器;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值