SuperSocket在.Net5中使用——启动篇

背景:上文介绍了基本概念,相比于官网来说不全,但也是基本能用到的概念了。本文继续将从启动SuperSocket的角度,继续介绍使用SuperSocket

1.两种启动方式

(1)通用启动方式,在任何.net5程序中都可以使用

     public static async Task Main(string[] args)
        {
            var host = SuperSocketHostBuilder.Create<TextPackageInfo, LinePipelineFilter>()
                .UsePackageHandler(async (s, p) => {
                    //对接收到的数据进行业务处理,并可以选择是否反馈给客户端数据
                    await s.SendAsync(Encoding.UTF8.GetBytes(p + "\r\n"));
                })
                .Build();
            //启动SuperSocketHostBuilder
            await host.RunAsync();
        }

上述几行代码就可以启动一个简单的Server:

(2)在.Net Core Web中启动,这样就可以在一个Web网站或者WebApi中同时启动一个Socket Server

public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                })
            .AsSuperSocketHostBuilder<TextPackageInfo, LinePipelineFilter>()
            .UsePackageHandler(async (s, p) =>
            {
                //对接收到的数据进行业务处理,并可以选择是否反馈给客户端数据
                await s.SendAsync(Encoding.UTF8.GetBytes(p + "\r\n"));
            });

 2.两种配置方式

在SuperSocket中,你可以很好的针对Server进行设置属性,并轻松的开启多个Server

(1)“概念篇”中已经介绍了SuperSocket的配置文件,通过在appsettings.json中添加serverOptions节点来配置Server选项,以及开启监听多个Server

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "serverOptions": {
    "name": "TestServer",
    "listeners": [
      {
        "ip": "127.0.0.1",
        "port": 4040,
        "sendTimeout": 20000,
        "maxPackageLength": 2048
      },
      {
        "ip": "Any",
        "port": 4041
      }
    ]
  },
  "AllowedHosts": "*"
}

上述配置项就同时监听了本机的4040和4041端口

(2)通过ConfigureSuperSocket方法配置需要

  var host = SuperSocketHostBuilder.Create<TextPackageInfo, LinePipelineFilter>()
                .ConfigureSuperSocket(options =>
                {
                    //配置SuperSocket选项
                    options.Name = "TestServer";
                    options.ReceiveBufferSize = 2048;
                    options.SendTimeout = 20000;
                    options.Listeners = new List<ListenOptions>(){
                   new ListenOptions{
                     Ip="Any",
                     Port = 4042
                        }
                    };
                })
                .UsePackageHandler(async (s, p) =>
                {
                    //对接收到的数据进行业务处理,并可以选择是否反馈给客户端数据
                    await s.SendAsync(Encoding.UTF8.GetBytes(p + "\r\n"));
                })
                .Build();

需要注意的是,这样会覆盖配置文件中关于SuperSocket的配置选项 。

3.使用过滤器

通过使用内置过滤器和自定义过滤器和进一步介绍SuperSocket中Filter的使用

(1)使用内置过滤器FixedSizePipelineFilter

  public class MyFixedSizePipelineFilter : FixedSizePipelineFilter<StringPackageInfo>
    {
        //规定一个长度为15有效数据的过滤器
        public MyFixedSizePipelineFilter() : base(15)
        {

        }
    }

过滤器绑定SuperSocket

var host = SuperSocketHostBuilder.Create<StringPackageInfo, MyFixedSizePipelineFilter>()
                .ConfigureSuperSocket(options =>
                {
                    //配置SuperSocket选项
                    options.Name = "TestServer";
                    options.ReceiveBufferSize = 2048;
                    options.SendTimeout = 20000;
                    options.Listeners = new List<ListenOptions>(){
                   new ListenOptions{
                     Ip="Any",
                     Port = 4042
                        }
                    };
                })
                .UsePackageHandler(async (s, p) =>
                {
                    //对接收到的数据进行业务处理,并可以选择是否反馈给客户端数据
                    await s.SendAsync(Encoding.UTF8.GetBytes(p + "\r\n"));
                })
                .Build();

启动发现,过滤器这边每次会截取过滤出长度为15的数据包,并解析成StringPackageInfo;数据长度不够时会放置到缓冲区等待拼接下次的数据包

 (2)自定义过滤器

官网上说内置过滤器能满足90%的场景,但是我觉得很多类型电文不会完全符合,这样可以在借鉴官网过滤数据的逻辑,自定义重写自己的数据过滤器,最主要的自己写的过滤器可以不必是命令行协议,即结束符不用必须得带\r\n

举例,现在有一个电文规定结束符是0X0A,数据包总长度为17,数据结构为:

 想必这样的电文结构大家平时接触很多,那现在就开始自己写过滤器了:

   /// <summary>
    /// 自定义数据过滤器
    /// </summary>
    public class MyFilter : IPipelineFilter<MyPackage>
    {
        private int _size = 17;
        private readonly byte[] _terminator= new byte[] { 0x0A};
        public IPackageDecoder<MyPackage> Decoder { get; set; }

        public object Context { get; set; }

        public IPipelineFilter<MyPackage> NextFilter => null;

        public MyPackage Filter(ref SequenceReader<byte> reader)
        {
            if (reader.Length < _size)
            {
                //如果长度小于规定协议数据包长度,不予解析
                return null;
            }
            if (!reader.TryReadTo(out ReadOnlySequence<byte> sequence, _terminator, advancePastDelimiter: false))
            {
                //如果结束符不是指定结束符,不予解析
                return null;
            }
            ReadOnlySequence<byte> buffer = reader.Sequence.Slice(0, 6);//type
            string type = EncodingExtensions.GetString(Encoding.UTF8, buffer).Trim();
            ReadOnlySequence<byte> buffer1 = reader.Sequence.Slice(5, 10);
            string userName= EncodingExtensions.GetString(Encoding.UTF8, buffer1).Trim();
            MyPackage myPackage = new MyPackage { Type=type,UserName=userName };
            while (reader.TryRead(out _)) ;
            return myPackage;
        }

        public void Reset() {
            
        }

    }

这个自定义过滤器中,继承IPipelineFilter接口,实现Filter方法来实现对数据包长度,结束符的检验,以及解析为数据结构。

执行结果,正常过滤解析后返回原数据:

接收数据不规范时:

可以看到,接收数据不规范时,会过滤掉不处理,更不会进行后续的业务操作。

以上就是SuperSocket的简单和基本使用方法,接下来一篇介绍Command的使用方法 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值