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);
            }
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM