热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SuperSocket封装成C#类库的步骤_C#教程

这篇文章主要介绍了SuperSocket封装成C#类库的步骤,帮助大家更好的理解和使用c#,感

将SuperSocket封装成类库之后可以将其集成进各种类型的应用,而不仅仅局限于控制台应用程序了,从而应用于不同的场景。这里以TelnetServer为例说明如何进行操作。

首先,创建一个C#类库项目LibSocketServer

添加SuperSocket引用(SuperSocket.Common.dll,SuperSocket.SocketBase.dll,SuperSocket.SocketEngine.dll),添加默认的日志框架log4net.dll引用。将log4net.config拷贝到项目文件夹的“Config”文件夹,然后设置它的“生成操作”为“内容”,设置它的“复制到输出目录”为“如果较新则复制”。

其次,添加SuperSocket完整的TelnetServer服务相关类,Socket服务管理类SocketServerManager。

其中SocketServerManager对Bootstrap的设置是SuperSocket封装为类库的关键。

TelnetSession.cs

using System;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol;
 
namespace LibSocketServer.Server
{
    public class TelnetSession : AppSession
    {
        protected override void OnSessionStarted()
        {
            Console.WriteLine($"New Session Connected: {RemoteEndPoint.Address} " +
                              $"@ {RemoteEndPoint.Port}.");
            Send("Welcome to SuperSocket Telnet Server.");
        }
 
        protected override void HandleUnknownRequest(StringRequestInfo requestInfo)
        {
            Console.WriteLine($"Unknown request {requestInfo.Key}.");
            Send("Unknown request.");
        }
 
        protected override void HandleException(Exception e)
        {
            Console.WriteLine($"Application error: {e.Message}.");
            Send($"Application error: {e.Message}.");
        }
 
        protected override void OnSessionClosed(CloseReason reason)
        {
            Console.WriteLine($"Session {RemoteEndPoint.Address} @ {RemoteEndPoint.Port} " +
                              $"Closed: {reason}.");
            base.OnSessionClosed(reason);
        }
    }
}

TelnetServer.cs

using System;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
 
namespace LibSocketServer.Server
{
    public class TelnetServer : AppServer
    {
        protected override bool Setup(IRootConfig rootConfig, IServerConfig config)
        {
            Console.WriteLine("TelnetServer Setup");
            return base.Setup(rootConfig, config);
        }
 
        protected override void OnStarted()
        {
            Console.WriteLine("TelnetServer OnStarted");
            base.OnStarted();
        }
 
        protected override void OnStopped()
        {
            Console.WriteLine();
            Console.WriteLine("TelnetServer OnStopped");
            base.OnStopped();
        }
    }
}

AddCommand.cs

using System;
using System.Linq;
using LibSocketServer.Server;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Protocol;
 
namespace LibSocketServer.Command
{
    public class AddCommand : CommandBase
    {
        public override string Name => "ADD";
        public override void ExecuteCommand(TelnetSession session, StringRequestInfo requestInfo)
        {
            Console.WriteLine($"{Name} command: {requestInfo.Body}.");
            session.Send(requestInfo.Parameters.Select(p => Convert.ToInt32(p)).Sum().ToString());
        }
    }
}

EchoCommand.cs

using System;
using LibSocketServer.Server;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Protocol;
 
namespace LibSocketServer.Command
{
    public class EchoCommand : CommandBase
    {
        public override string Name => "ECHO";
        public override void ExecuteCommand(TelnetSession session, StringRequestInfo requestInfo)
        {
            Console.WriteLine($"{Name} command: {requestInfo.Body}.");
            session.Send(requestInfo.Body);
        }
    }
}

SocketServerManager.cs

using System;
using System.Reflection;
using SuperSocket.SocketBase;
using SuperSocket.SocketEngine;
 
namespace LibSocketServer
{
    public class SocketServerManager
    {
        private readonly IBootstrap _bootstrap;
 
        public bool Startup(int port)
        {
            if (!_bootstrap.Initialize())
            {
                Console.WriteLine("SuperSocket Failed to initialize!");
                return false;
            }
 
            var ret = _bootstrap.Start();
            Console.WriteLine($"SuperSocket Start result: {ret}.");
 
            return ret == StartResult.Success;
        }
 
        public void Shutdown()
        {
            _bootstrap.Stop();
        }
 
        #region Singleton
 
        private static SocketServerManager _instance;
        private static readonly object LockHelper = new object();
 
        private SocketServerManager()
        {
            var location = Assembly.GetExecutingAssembly().Location;
            var cOnfigFile= $"{location}.config";
            _bootstrap = BootstrapFactory.CreateBootstrapFromConfigFile(configFile);
        }
 
        public static SocketServerManager Instance
        {
            get
            {
                if (_instance != null)
                {
                    return _instance;
                }
 
                lock (LockHelper)
                {
                    _instance = _instance ?? new SocketServerManager();
                }
 
                return _instance;
            }
        }
 
        #endregion
    }
}

再次,添加配置文件App.config到类库中,并设置其配置参数。



    
        
                                                                                                       

最后,创建控制台项目TelnetServerSample,添加项目引用LibSocketServer,然后在Program类中使用SocketServerManager进行SuperSocket的调用。

Program.cs

using System;
using LibSocketServer;
 
namespace TelnetServerSample
{
    class Program
    {
        static void Main()
        {
            try
            {
                //启动SuperSocket
                if (!SocketServerManager.Instance.Startup(2021))
                {
                    Console.WriteLine("Failed to start TelnetServer!");
                    Console.ReadKey();
                    return;
                }
 
                Console.WriteLine("TelnetServer is listening on port 2021.");
                Console.WriteLine();
                Console.WriteLine("Press key 'q' to stop it!");
                Console.WriteLine();
                while (Console.ReadKey().KeyChar.ToString().ToUpper() != "Q")
                {
                    Console.WriteLine();
                }
 
                //关闭SuperSocket
                SocketServerManager.Instance.Shutdown();
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
            }
 
            Console.WriteLine();
            Console.WriteLine("TelnetServer was stopped!");
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}

GitHub Sample


推荐阅读
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 本文介绍了sqlserver云存储和本地存储的区别,云存储是将数据存储在网络上,方便查看和调用;本地存储是将数据存储在电脑磁盘上,只能在存储的电脑上查看。同时提供了几种启动sqlserver的方法。此外,还介绍了如何导出数据库的步骤和工具。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 本文介绍了自动化测试专家Elfriede Dustin在2008年的文章中讨论了自动化测试项目失败的原因。同时,引用了IDT在2007年进行的一次软件自动化测试的研究调查结果,调查显示很多公司认为自动化测试很有用,但很少有公司成功实施。调查结果表明,缺乏资源是导致自动化测试失败的主要原因,其中37%的人认为缺乏时间。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 本文介绍了一个React Native新手在尝试将数据发布到服务器时遇到的问题,以及他的React Native代码和服务器端代码。他使用fetch方法将数据发送到服务器,但无法在服务器端读取/获取发布的数据。 ... [详细]
  • 本文介绍了使用数据库管理员用户执行onstat -l命令来监控GBase8s数据库的物理日志和逻辑日志的使用情况,并强调了对已使用的逻辑日志是否及时备份的重要性。同时提供了监控方法和注意事项。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
author-avatar
天边的云YEAH_988
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有