zoukankan      html  css  js  c++  java
  • SuperSocket 2.0学习05:扩展你的AppSession和SuperSocketService

    官方学习资料:扩展你的AppSession和SuperSocketService

    本文开发环境:Win10 + VS2019 + .NetCore 3.1 + SuperSocket 2.0.0-beta.8。

    Gitee:SuperSocketV2Sample

    SuperSocket 2.0中的AppSession和SuperSocket 1.6版本的类似,管理着和Client的连接。SuperSocket 2.0中的SuperSocketService对应于SuperSocket 1.6中的AppServer,负责AppSession的管理,是服务器级别的类。

    1、创建项目

    使用VS2019创建.NET Core控制台程序,选择.Net Core 3.1,通过NuGet引入SuperSocket(2.0.0-beta.8)。

    2、添加配置文件

    在项目根目录添加appsettings.json配置文件,并设置其文件属性为“如果较新则复制”。

    3、Session和Service 

    using System;
    using System.Text;
    using System.Threading.Tasks;
    using SuperSocket;
    using SuperSocket.Channel;
    using SuperSocket.Server;
    
    namespace SuperSocketV2Sample.Service.Server
    {
        public class TelnetSession : AppSession
        {
            protected override async ValueTask OnSessionConnectedAsync()
            {
                Console.WriteLine($@"{DateTime.Now} [TelnetSession] New Session connected: {RemoteEndPoint}.");
    
                //发送消息给客户端
                var msg = $@"Welcome to TelnetServer: {RemoteEndPoint}";
                await (this as IAppSession).SendAsync(Encoding.UTF8.GetBytes(msg + "
    "));
            }
    
            protected override async ValueTask OnSessionClosedAsync(CloseEventArgs e)
            {
                Console.WriteLine($@"{DateTime.Now} [TelnetSession] Session {RemoteEndPoint} closed: {e.Reason}.");
                await Task.Delay(0);
            }
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Options;
    using SuperSocket;
    using SuperSocket.Channel;
    using SuperSocket.Server;
    
    namespace SuperSocketV2Sample.Service.Server
    {
        public class TelnetService<TReceivePackageInfo> : SuperSocketService<TReceivePackageInfo>
            where TReceivePackageInfo : class
        {
            private readonly List<IAppSession> _appSessions;
            private readonly CancellationTokenSource _tokenSource;
    
            public TelnetService(IServiceProvider serviceProvider, IOptions<ServerOptions> serverOptions)
                : base(serviceProvider, serverOptions)
            {
                _appSessions = new List<IAppSession>();
                _tokenSource = new CancellationTokenSource();
            }
    
            protected override async ValueTask OnSessionConnectedAsync(IAppSession session)
            {
                Console.WriteLine($@"{DateTime.Now} [TelnetService] " +
                                  $@"Session connected: {session.RemoteEndPoint}.");
    
                lock (_appSessions)
                {
                    _appSessions.Add(session);
                }
    
                await base.OnSessionConnectedAsync(session);
            }
    
            protected override async ValueTask OnSessionClosedAsync(IAppSession session, CloseEventArgs e)
            {
                Console.WriteLine($@"{DateTime.Now} [TelnetService] " +
                                  $@"Session {session.RemoteEndPoint} closed : {e.Reason}.");
    
                lock (_appSessions)
                {
                    _appSessions.Remove(session);
                }
    
                await base.OnSessionClosedAsync(session, e);
            }
    
            protected override async ValueTask OnStartedAsync()
            {
                Console.WriteLine($@"{DateTime.Now} TelnetService started.");
                StatisticAsync(_tokenSource.Token, 5000).GetAwaiter();
                await Task.Delay(0);
            }
    
            protected override async ValueTask OnStopAsync()
            {
                _tokenSource.Cancel();
                Console.WriteLine($@"{DateTime.Now} TelnetService stop.");
                await Task.Delay(0);
            }
    
            private async Task StatisticAsync(CancellationToken token, int interval)
            {
                while (true)
                {
                    try
                    {
                        //超时等待
                        await Task.Delay(interval, token);
                    }
                    catch (Exception)
                    {
                        break;
                    }
                    
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
    
                    //统计数据
                    var sessionList = new List<string>();
                    lock (_appSessions)
                    {
                        foreach (var session in _appSessions)
                        {
                            sessionList.Add(session.RemoteEndPoint.ToString());
                        }
                    }
    
                    if (sessionList.Count == 0)
                    {
                        Console.WriteLine($@"{DateTime.Now} No session connected.");
                        continue;
                    }
    
                    var sb = new StringBuilder();
                    sb.AppendLine($@"{DateTime.Now} {sessionList.Count} sessions connected:");
                    foreach (var session in sessionList)
                    {
                        sb.AppendLine($"	{session}");
                    }
    
                    Console.WriteLine(sb.ToString());
                }
            }
        }
    }

    4、测试代码

    using System;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    using SuperSocket;
    using SuperSocket.Command;
    using SuperSocket.ProtoBase;
    using SuperSocketV2Sample.Service.Commands;
    using SuperSocketV2Sample.Service.Server;
    
    namespace SuperSocketV2Sample.Service
    {
        class Program
        {
            static async Task Main()
            {
                //创建宿主:用Package的类型和PipelineFilter的类型创建SuperSocket宿主。
                var host = SuperSocketHostBuilder.Create<StringPackageInfo, CommandLinePipelineFilter>()
                    //注入TelnetService
                    .UseHostedService<TelnetService<StringPackageInfo>>()
                    //注入TelnetSession
                    .UseSession<TelnetSession>()
                    //注册用于处理连接、关闭的Session处理器
                    .UseSessionHandler(async (session) =>
                    {
                        Console.WriteLine($"{DateTime.Now} [SessionHandler] Session connected: {session.RemoteEndPoint}");
                        await Task.Delay(0);
                    }, async (session, reason) =>
                    {
                        Console.WriteLine($"{DateTime.Now} [SessionHandler] Session {session.RemoteEndPoint} closed: {reason}");
                        await Task.Delay(0);
                    })
                    //注入命令
                    .UseCommand((commandOptions) =>
                    {
                        commandOptions.AddCommand<AddCommand>();
                        commandOptions.AddCommand<DivCommand>();
                        commandOptions.AddCommand<MulCommand>();
                        commandOptions.AddCommand<SubCommand>();
                        commandOptions.AddCommand<EchoCommand>();
                    })
                    //配置日志
                    .ConfigureLogging((hostCtx, loggingBuilder) =>
                    {
                        loggingBuilder.AddConsole();
                    })
                    .Build();
                try
                {
                    await host.RunAsync();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
        }
    }
  • 相关阅读:
    Github 上热门的 Spring Boot 项目实战推荐
    深入理解建造者模式 ——组装复杂的实例
    别死写代码,这 25 条比涨工资都重要
    Spring Boot 使用 JWT 进行身份和权限验证
    秋招打怪升级之路:十面阿里,终获offer!
    一问带你区分清楚Authentication,Authorization以及Cookie、Session、Token
    适合新手入门Spring Security With JWT的Demo
    面试官:“谈谈Spring中都用到了那些设计模式?”。
    春夏秋冬又一春之Redis持久化
    Mysql锁机制简单了解一下
  • 原文地址:https://www.cnblogs.com/xhubobo/p/14622249.html
Copyright © 2011-2022 走看看