您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > .NET

asp.net core supersocket介绍以及源码分析

时间:2022-10-17 17:39:27  来源:  作者:大好fish

物联网设备常用的通信协议有TCP,MQTT.今天我们介绍的是TCP连接,TCP连接程序的组件有Supersocket,do.NETty.Supersocket相信搞过.net的朋友应该都知道,dotnetty是有微软Azure从JAVA平台下移植过来的一个高性能、异步事件驱动的 NIO 框架,Kafka和RocketMQ等消息中间件、ElasticSearch开源搜索引擎、大数据处理Hadoop的RPC框架Avro、分布式通信框架Dubbo,都使用了Netty,Netty的资料很多,有兴趣的可以搜一下,dotnetty和Netty语法基本一致,所以资料可以互相参考,今天我们介绍的是.net下supersocket的使用以及源码分析

SuperSocket 可以和 ASP.NET Core 网站一起同时运行。你需要做的是将 SuperSocket 注册到 ASP.NET Core 网站的host builder中去, 同时将服务器的选项放到配置文件中或者通过代码定义。

  //don't forget the usings
    using SuperSocket;
    using SuperSocket.ProtoBase;

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            })
            .AsSuperSocketHostBuilder<TextPackageInfo, LinePipelineFilter>()
            .UsePackageHandler(async (s, p) =>
            {
                // echo message back to client
                awAIt s.SendAsync(Encoding.UTF8.GetBytes(p.Text + "rn"));
            });

同时将服务器的配置选项放到配置文件 "Appsettings.json" 中去:

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

上面代码就可以实现supersocket和asp.net core (.net core3,.net5,.net6)的集成,可以支持最新的.NET6,当然DotNetty也支持.Net 6

今天我们分析源码的版本是supersocket V2.0的版本,跟之前.net freamwork下有很大的区别

SuperSocket 请求处理模型示意图

 

SuperSocket 请求处理模型示意图

 

源码主线流程分析

 

主流程图

1分析的入口就从SuperSocketService这个类开始,他集成自IHostedService, IServer,因此这个类的StartAsync就是执行的入口

 async Task<bool> IServer.StartAsync()
        {
            await StartAsync(CancellationToken.None);
            return true;
        }

 

2.通过channelCreatorFactory创建监听器,监听代码如下

 

  public bool Start()
        {
            var options = Options;

            try
            {
                if (options.Security != SslProtocols.None && options.CertificateOptions != null)
                {
                    options.CertificateOptions.EnsureCertificate();
                }

                var listenEndpoint = options.GetListenEndPoint();
                var listenSocket = _listenSocket = new Socket(listenEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                
                listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                listenSocket.LingerState = new LingerOption(false, 0);

                if (options.NoDelay)
                    listenSocket.NoDelay = true;
                
                listenSocket.Bind(listenEndpoint);
                listenSocket.Listen(options.BackLog);

                IsRunning = true;

                _cancellationTokenSource = new CancellationTokenSource();

                KeepAccept(listenSocket).DoNotAwait();
                return true;
            }
            catch (Exception e)
            {
                _logger.LogError(e, $"The listener[{this.ToString()}] failed to start.");
                return false;
            }
        }

3.开启异步接收accept线程

 

        private async Task KeepAccept(Socket listenSocket)
        {
            while (!_cancellationTokenSource.IsCancellationRequested)
            {
                try
                {
                    var client = await listenSocket.AcceptAsync().ConfigureAwait(false);
                    OnNewClientAccept(client);
                }
                catch (Exception e)
                {
                    if (e is ObjectDisposedException || e is NullReferenceException)
                        break;
                    
                    if (e is SocketException se)
                    {
                        var errorCode = se.ErrorCode;

                        //The listen socket was closed
                        if (errorCode == 125 || errorCode == 89 || errorCode == 995 || errorCode == 10004 || errorCode == 10038)
                        {
                            break;
                        }
                    }
                    
                    _logger.LogError(e, $"Listener[{this.ToString()}] failed to do AcceptAsync");
                    continue;
                }
            }

            _stopTaskCompletionSource.TrySetResult(true);
        }

4 当有连接进来后,执行执行注册的事件

listener.NewClientAccepted += OnNewClientAccept;

 

5.accepted后就创建新的Channel,session

 

     private void AcceptNewChannel(IChannel channel)
        {
            var session = _sessionFactory.Create() as AppSession;
            HandleSession(session, channel).DoNotAwait();
        }

6 channel.Start(),

  public override void Start()
        {
            _readsTask = ProcessReads();
            _sendsTask = ProcessSends();
            WaitHandleClosing();
        }

 

7.将从内核里读的socket数据异步写到 Pipe中

           protected virtual async Task ProcessReads()
        {
            var pipe = In;

            Task writing = FillPipeAsync(pipe.Writer);
            Task reading = ReadPipeAsync(pipe.Reader);

            await Task.WhenAll(reading, writing);
        }

8当Pipe有数据写入后,通知Pipe读线程去解析数据,这里通知用的方法是
ManualResetValueTaskSourceCore,写线程写入数据后执行 _taskSourceCore.SetResult(target);

就会触发读线程去读,读的时候会根据你设置的协议模版去解析,这个过程会去处理粘包和拆包的过程,

因为Pipe是可以定向的从流中取部分数据的

内置的协议模板如下;

TerminatorReceiveFilter (SuperSocket.SocketBase.Protocol.TerminatorReceiveFilter, SuperSocket.SocketBase)

CountSpliterReceiveFilter (SuperSocket.Facility.Protocol.CountSpliterReceiveFilter, SuperSocket.Facility)

FixedSizeReceiveFilter (SuperSocket.Facility.Protocol.FixedSizeReceiveFilter, SuperSocket.Facility)

BeginEndMarkReceiveFilter (SuperSocket.Facility.Protocol.BeginEndMarkReceiveFilter, SuperSocket.Facility)

FixedHeaderReceiveFilter (SuperSocket.Facility.Protocol.FixedHeaderReceiveFilter, SuperSocket.Facility)

 

9 读取到的数据解析成packageInfo 后继续往下执行

      await foreach (var p in packageChannel.RunAsync())
                {
                    if(_packageHandlingContextAccessor!=null)
                    {
                        _packageHandlingContextAccessor.PackageHandlingContext = new PackageHandlingContext<IAppSession, TReceivePackageInfo>(session, p);
                    }
                    await packageHandlingScheduler.HandlePackage(session, p);
                }

10再执行到我们定义的command即可

        ValueTask IPackageHandler<TNetPackageInfo>.Handle(IAppSession session, TNetPackageInfo package)
        {
            return HandlePackage(session, PackageMapper.Map(package));
        }

11 执行我们预制的command代码

 

    [Command("add")]
    public class ADD : IAsyncCommand<StringPackageInfo>
    {
        public async ValueTask ExecuteAsync(IAppSession session, StringPackageInfo package)
        {
            var result = package.Parameters
                .Select(p => int.Parse(p))
                .Sum();

            await session.SendAsync(Encoding.UTF8.GetBytes(result.ToString() + "rn"));
        }
    }


Tags:asp.net   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
深入理解 ASP.NET Core 中间件技术
什么是ASP.NET Core的中间件技术在ASP.NET Core中,中间件技术是一种处理HTTP请求和响应的机制。中间件是一个组件,可以在请求到达应用程序之前或响应离开应用程序之前对其进...【详细内容】
2023-07-09  Search: asp.net  点击:(94)  评论:(0)  加入收藏
ASP.NET Core依赖注入原理详解与Autofac库深度集成实践
在ASP.NET Core中,依赖注入(DI)是非常重要的特性。本文将深入探讨ASP.NET Core源码中的容器IOC和依赖注入的实现原理。什么是IoCInversion of Control(IoC)是指将控制权反转过来,...【详细内容】
2023-06-15  Search: asp.net  点击:(226)  评论:(0)  加入收藏
详解 ASP.NET Core 运行时之模块化设计
整体上可以分为以下几个模块:应用程序托管模块应用程序托管模块是入口点,主要负责创建 Host、解析 ConfigureServices 和 Configure 方法,创建 Pipeline 等。Host 是应用程序的...【详细内容】
2023-05-21  Search: asp.net  点击:(218)  评论:(0)  加入收藏
Asp.Net Core自定义配置中心客户端
说明:下面的实例是通过阅读Nacos的SDK源码,提取出来的关键实现。Asp.Net core添加一个自定义配置,只要通过IConfigurationBuilder的Add方法,传递一个实现了IConfigurationSource...【详细内容】
2023-02-23  Search: asp.net  点击:(235)  评论:(0)  加入收藏
ASP.NET原创框架十-应用模块开发之页面生成
关于应用模块页面的生成应用模块页面函数如:public partial class userblog : BaseJsonMode{[ModeMethod("{CanNoLogin:true,CanEnable:true}")]static public ReturnJson i...【详细内容】
2022-11-19  Search: asp.net  点击:(486)  评论:(0)  加入收藏
asp.net core supersocket介绍以及源码分析
跟物联网设备常用的通信协议有TCP,MQTT.今天我们介绍的是TCP连接,TCP连接程序的组件有Supersocket,dotnetty.Supersocket相信搞过.net的朋友应该都知道,dotnetty是有微软Azu...【详细内容】
2022-10-17  Search: asp.net  点击:(690)  评论:(0)  加入收藏
asp.net core源码如何实现监听Http请求,分析Kestrel看一下过程
#asp.net core#先让我们看一下最小API的代码,通过以下几行代码就可以搭建一个简单的asp.net core web服务器,是不是十分简洁?var builder = WebApplication.CreateBuilder(a...【详细内容】
2022-10-04  Search: asp.net  点击:(470)  评论:(0)  加入收藏
Asp.Net Core Identity 多数据库支持
Asp.Net Core Identity 是.Net自带的身份认证系统,支持用户界面 (UI) 登录功能,并且管理用户、密码、配置文件数据、角色、声明、令牌、电子邮件确认等等。使用Visual Studio...【详细内容】
2022-06-05  Search: asp.net  点击:(266)  评论:(0)  加入收藏
Asp.Net在线预览Word文档的解决方案与思路
前几天有个老项目找到我,有多老呢?比我工作年限都长,见到这个项目我还得叫一声前辈。这个项目目前使用非常稳定,十多年了没怎么更新过,现在客户想加一个小功能:在线预览Word文档。...【详细内容】
2022-04-27  Search: asp.net  点击:(414)  评论:(0)  加入收藏
理解ASP.NET Core - 授权(Authorization)
之前,我们已经了解了ASP.NET Core中的身份认证,现在,我们来聊一下授权。老规矩,示例程序源码XXTk.Auth.Samples已经提交了,需要的请自取。概述ASP.NET Core中的授权方式有很多,我...【详细内容】
2022-04-20  Search: asp.net  点击:(685)  评论:(0)  加入收藏
▌简易百科推荐
.Net开发中十种常见的内存错误以及相应的解决方案
在.Net开发中,为内存管理方面提供了许多便利,但仍然存在一些常见的错误和陷阱。这些错误可能导致内存泄漏、性能下降、异常抛出等问题,严重影响应用程序的稳定性和性能。在软件...【详细内容】
2024-03-26  小乖兽技术  今日头条  Tags:.Net   点击:(13)  评论:(0)  加入收藏
.NET配置文件大揭秘:轻松读取JSON、XML、INI和环境变量
概述:.NET中的IConfiguration接口提供了一种多源读取配置信息的灵活机制,包括JSON、XML、INI文件和环境变量。通过示例,清晰演示了从这些不同源中读取配置的方法,使配置获取变得...【详细内容】
2023-12-28  架构师老卢  今日头条  Tags:.NET   点击:(92)  评论:(0)  加入收藏
.Net开发都应当掌握的泛型基础知识集合
在C#编程语言中,泛型是一项非常强大和重要的功能。它允许我们编写更加灵活和通用的代码,同时提高代码的可重用性和性能。本文将介绍C#泛型的一些关键知识点,帮助读者理解和应用...【详细内容】
2023-12-25  小乖兽技术  今日头条  Tags:.Net   点击:(125)  评论:(0)  加入收藏
作为 .NET 开发人员,我为什么开始使用 Python?
作者 | Alex Maher编译 | 小欧作为一名 .NET 开发人员,很长一段时间以来,我一直关注 C# 和 .NET 的出色工具和功能。但我最近开始使用 Python,感觉非常棒。这里申明一点,这篇文...【详细内容】
2023-12-25    51CTO  Tags:.NET   点击:(143)  评论:(0)  加入收藏
.NET Core 3.1 升级到 .NET 8,看看都有哪些变化
.NET Core 3.1 已经用了很长一段时间,其实在 2022 年的年底微软已经不提供支持了,后面的一个 LTS 版本 .NET 6 也会在 2024 年 11 月终止支持,所以直接升级到 .NET 8 是最好的...【详细内容】
2023-12-08  不止dotNET  微信公众号  Tags:.NET   点击:(192)  评论:(0)  加入收藏
.NET Core的中间件来对Web API进行流量限制实现方法
在.NET Core中,我们可以使用ASP.NET Core的中间件来对Web API进行流量限制。ASP.NET Core提供了一个名为RateLimit的开源库,可以方便地实现流量限制功能。下面将详细介绍如何...【详细内容】
2023-12-06  架构师老卢  今日头条  Tags:.NET   点击:(177)  评论:(0)  加入收藏
微软官方出品微服务架构:十个.Net开源项目
1、一个高性能类型安全的.NET枚举实用开源库Enums.NET是一个.NET枚举实用程序库,专注于为枚举提供丰富的操作方法。它支持.NET Framework和.Net Core。它主要优点表现在类型...【详细内容】
2023-12-06  编程乐趣  今日头条  Tags:.Net   点击:(133)  评论:(0)  加入收藏
.NET开源的处理分布式事务的解决方案
前言在分布式系统中,由于各个系统服务之间的独立性和网络通信的不确定性,要确保跨系统的事务操作的最终一致性是一项重大的挑战。今天给大家推荐一个.NET开源的处理分布式事务...【详细内容】
2023-11-30  追逐时光者  微信公众号  Tags:.NET   点击:(173)  评论:(0)  加入收藏
深入 .NET 异步编程:Task 与 ValueTask 的区别与选择
在 .NET 中,Task 和 ValueTask 都是用于表示异步操作的类型,但它们有一些重要的区别。TaskTask 是最常见的表示异步操作的类型。它通常用于表示耗时的、异步的操作,比如从文件...【详细内容】
2023-11-26  架构师老卢  微信公众号  Tags: .NET   点击:(190)  评论:(0)  加入收藏
.NET字符串存储:解析常量与动态字符串,深入了解内存机制
在 .NET 中,字符串是不可变的,这意味着一旦创建,字符串的内容就不能被修改。字符串在内存中以不同的方式存储,具体取决于它是常量字符串还是动态创建的字符串。常量字符串常量字...【详细内容】
2023-11-25  架构师老卢  微信公众号  Tags:.NET   点击:(196)  评论:(0)  加入收藏
站内最新
站内热门
站内头条