Net6/SuperSocket2.0课程1,一个Telnet示例

十年河东,十年河西,莫欺少年穷

学无止境,精益求精

1、新建控制台程序并引入包

dotnet add package SuperSocket.Server

 2、书写代码

using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SuperSocket;
using SuperSocket.ProtoBase;

namespace MySupersocket // Note: actual namespace depends on the project name.
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            var Listeners = new List<ListenOptions>() {  new ListenOptions
        {
            Ip = "Any",
            Port = 4040
        }, new ListenOptions
        {
            Ip = "Any",
            Port = 8040
        }};
            var host = SuperSocketHostBuilder
     .Create<StringPackageInfo, CommandLinePipelineFilter>().UsePackageHandler(async (session, package) =>
     {
         var result = 0;
         //接收的包 类型为StringPackageInfo 也就是字符串
         Console.WriteLine($"package如下:");
         Console.WriteLine(JsonConvert.SerializeObject(package));
         //session 可以理解为客户端的某个连接
         Console.WriteLine($"session如下:");
         //客户端关闭连接原因
         Console.WriteLine("ChannelCloseReason:" + session.Channel.CloseReason); 
         //客户端最后活跃时间
         Console.WriteLine("LastActiveTime:" + session.LastActiveTime);
         //服务器侦听的IP+端口,也就是侦听地址
         Console.WriteLine("LocalEndPoint:" + session.LocalEndPoint);
         //客户端IP+端口,也就是客户端地址
         Console.WriteLine("RemoteEndPoint:" + session.RemoteEndPoint);
         //当前客户端连接数量
         Console.WriteLine("SessionCount:" + session.Server.SessionCount);
         //当前服务器侦听的状态
         Console.WriteLine("ServerState:" + session.Server.State);
         //当前链接的唯一标识
         Console.WriteLine("SessionID:" + session.SessionID);
         //当前链接的开始时间
         Console.WriteLine("StartTime:" + session.StartTime);
         //当前链接的状态
         Console.WriteLine("State:" + session.State);
         switch (package.Key.ToUpper())
         {
             case ("ADD"):
                 result = package.Parameters
                     .Select(p => int.Parse(p))
                     .Sum();
                 break;

             case ("SUB"):
                 result = package.Parameters
                     .Select(p => int.Parse(p))
                     .Aggregate((x, y) => x - y);
                 break;

             case ("MULT"):
                 result = package.Parameters
                     .Select(p => int.Parse(p))
                     .Aggregate((x, y) => x * y);
                 break;
         }
         // \r\n 为键盘回车换行
         await session.SendAsync(Encoding.UTF8.GetBytes(result.ToString() + "\r\n"));
     }).ConfigureSuperSocket(options =>
     {
         options.Name = "Echo Server";
         options.Listeners = Listeners;
     }).ConfigureLogging((hostCtx, loggingBuilder) =>
     {
         loggingBuilder.AddConsole();
     }).Build();
            await host.RunAsync();
            Console.Read();
        }
    }
}
View Code

3、使用telnet测试

telnet 127.0.0.1 8040

NetCore输出

 4、概念解读

4.1、Package Type(包类型/内置行协议)

TextPackageInfo

 包类型 TextPackageInfo(SuperSocket.ProtoBase.TextPackageInfo,SuperSocket.ProtoBase) 是在 SuperSocket 中定义的最简单的数据包。它代表这类型的包仅包含一个字符串。

namespace SuperSocket.ProtoBase
{
    public class TextPackageInfo
    {
        public string Text { get; set; }

        public override string ToString()
        {
            return Text;
        }
    }
}

StringPackageInfo

StringPackageInfo是简单的包括键值和body的数据结构,一些内置Filter默认将过滤好的数据解析为StringPackageInfo类。StringPackageInfo类使用了一个空格来分割请求key和参数

namespace SuperSocket.ProtoBase
{
    public class StringPackageInfo : IKeyedPackageInfo<string>, IStringPackage
    {
        public string Key { get; set; }

        public string Body { get; set; }

        public string[] Parameters { get; set; }
    }
}

4.2、AppSession

AppSession

根据官方描述,AppSession代表一个和客户端的逻辑连接,基于连接的操作应该定于在该类之中。你可以用该类的实例发送数据到客户端,接收客户端发送的数据或者关闭连接。

对于实现固定头协议来说,AppSession不是必须的,但是站在应用服务器的角度来说,一个AppSession对象就是一个客户端连接,该客户端起码会含有标识自己的信息,这是应用服务器所需要的。

4.3、PipelineFilter 行协议过滤器

SuperSocket 提供了这些 PipelineFilter 模版:

TerminatorPipelineFilter (SuperSocket.ProtoBase.TerminatorPipelineFilter, SuperSocket.ProtoBase)
TerminatorTextPipelineFilter(SuperSocket.ProtoBase.TerminatorTextPipelineFilter, SuperSocket.ProtoBase)
LinePipelineFilter (SuperSocket.ProtoBase.LinePipelineFilter, SuperSocket.ProtoBase)
CommandLinePipelineFilter (SuperSocket.ProtoBase.CommandLinePipelineFilter, SuperSocket.ProtoBase)  
BeginEndMarkPipelineFilter (SuperSocket.ProtoBase.BeginEndMarkPipelineFilter, SuperSocket.ProtoBase) 
FixedSizePipelineFilter (SuperSocket.ProtoBase.FixedSizePipelineFilter, SuperSocket.ProtoBase)  
FixedHeaderPipelineFilter (SuperSocket.ProtoBase.FixedHeaderPipelineFilter, SuperSocket.ProtoBase) 

1、TerminatorPipelineFilter 终止符过滤器(过滤解析指定终止符之前的数据,默认解析成StringPackageInfo类)

2、TerminatorTextPipelineFilter 终止符文本管道过滤器(过滤解析指定终止符之前的数据,默认解析成TextPackageInfo类)

3、LinePipelineFilter 管路过滤器(最普通的过滤器,除了命令行限制,其他无限制,默认解析成TextPackageInfo类)

4、CommandLinePipelineFilter 命令行管道过滤器(最普通的过滤器,除了命令行限制,其他无限制,默认解析成StringPackageInfo类)

5、BeginEndMarkPipelineFilter 有固定开始结束标记管道过滤器(根据开始和结束符过滤有效数据,默认解析成StringPackageInfo类)

6、FixedSizePipelineFilter 固定长度过滤器(只解析指定长度的数据,当数据长度小于指定长度时,会报错并断开连接重连,默认解析成StringPackageInfo类)

7、FixedHeaderPipelineFilter 固定开头(长度)管道过滤器(通过指定数据包开头长度,重写GetBodyLengthFromHeader方法,从开头数据包中获取有效数据包的长度,默认解析成StringPackageInfo类)

 

 参考博客:https://blog.csdn.net/weixin_33277597/article/details/122051837

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章