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 + "\r\n"));
        }

        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($"\t{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);
            }
        }
    }
}
posted @ 2021-04-06 15:57  xhubobo  阅读(1183)  评论(6编辑  收藏  举报