分享

可扩展多线程异步Socket服务器框架EMTASS 2.0

 sofes 2011-03-20

可扩展多线程异步Socket服务器框架EMTASS 2.0(来源:http://blog.csdn.net/hulihui) 收藏

< type="text/javascript"> (来源:http://blog.csdn.net/hulihui )

0 前言

>>[前言][第1节][第2节][第3节][第4节][第5节][第6节]
在程序设计与实际应用中,Socket数据包接收服务器够得上一个经典问题了:需要计算机与网络编程知识(主要是Socket),与业务处理逻辑密切 (如:包组成规则),同时还要兼顾系统运行的稳定、效率、安全与管理等。具体应用时,在满足业务处理逻辑要求的基础上,存在侧重点:有些需要考虑并发与效 率,有些需要强调稳定与可靠等等。虽然.NET 2.0 Framework上的IOCP(I/O完成端口)异步技术可以有效解决并发等问题,但完全的异步模式也缺乏一些控制上的灵活性,例如:Socket暂停 操作等。 本文介绍的是一个传统Socket数据包服务器解决方案,该方案改自笔者2005年底的一个交通部省级公路交通流量数据服务器中心 (DSC)项目。当时.NET Framework 2.0 与 Visual Studio 2005 发布没多久,笔者接触C#的时间不长。于是Google了国内国外网,希望找点应用C#解决Socket通信问题的思路和代码。最后,找到了两篇帮助最大 的文章:一篇是国人2005年3月写的Socket接收器框架——在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一) (分 (一)、(二)两篇),该文应用了客户端Socket会话(Session)概念;另一篇是美国人写的,提出了多线程、分段接收数据包的技术方案,描述了 多线程、异步Socket的许多实现细节,该文坚定了笔者采用多线程和异步方式处理Socket接收器的技术路线。第一个版本EMTASS 1.0(EMTASS,Extensible Multi-Thread Asynchronous Socket Server)于2006年初完成并投入使用。 今年暑假,笔者修改了原Socket接收服务器代码,即EMTASS 1.1。最近,又按框架的可扩展性、可重用性等要求重新构思和设计了EMTASS,即EMTASS 2.0。下面的介绍共分六个部分:
  1. 总体思路与架构
  2. 关键实现技术
  3. 框架使用简介
  4. 一般测试结果
  5. 总结与展望
  6. 版本与源码

1 总体思路与架构

>>[前言][第1节][第2节][第3节][第4节][第5节][第6节]

1.1 总体思路

总体构思上,主要考虑多线程、异步Socket和可扩展性三个方面。

1) 三个核心线程

在Internet环境下的Socket应用中,客户端和网络容易出现异常,此时必须释放异常退出的Socket资源。考虑到服务器的高并 发能力,一般采取包接收和处理分开的策略:将接收到的包添加到包队列,然后处理队列中的数据包。当然,侦听远程客户端的连接请求可以用Socket的 AcceptAsync()异步方法(IOCP,I/O完成端口由此开始)。考虑到暂停、关闭同步操作,仍然用一个线程。这样,清理资源、处理数据包、侦 停客户连接请求就是组成了EMTASS架构的三个核心线程,它们由.NET线程池统一管理:
  1. 客户端连接侦听线程 StartServerListen(): 循环侦听远程客户端的Socket连接请求。如果存在,通过适当规范性判断 后创建该Socket的客户端会话TSessionBase对象(实际上是该类的派生类对象),同时调用该会话对象的Socket异步数据接收方法 BeginReceive(),接收到的数据包存放在会话对象的包队列中。当然,新增的TSessionBase对象将添加到会话队列 m_sessionTable(一个Dictionary<>泛型对象)中,该队列表就是清理和处理线程的遍历对象;
  2. 数据包处理线程 CheckDatagramQueue(): 循环检测TSessonBase队列中的会话对象,调用该对象的相关方法完成数据包解析、判断类型、数据存储等任务;
  3. 会话表检测线程 CheckSessionTable(): 循环检查会话表m_sessionTable中的各个会话对象,分步骤清理已经超时、无效或异常的会话对象,清理会话对象的缓冲区,释放其Socket资源。

2) 异步处理模式

.NET Framework中的Socket具有完整的异步处理能力:侦听后异步接收(AcceptAsync())、数据异步接收 (BeginReceive())、数据异步发送(BeginSend())等。EMTASS框架采取了异步接收和发送方式,并封装在 TSessionBase类中。在EMTASS的版本1.0、1.1中,这些方法在主类TSocketServerBase中实现,显然不符合类封装原 则。

3) 系统可扩展性

可扩展性主要考虑不同的业务处理逻辑和应用场景,即:数据包格式、数据存储方法、数据库服务器等。框架EMTASS的可扩展性体现在类的泛型与抽象设计、方法虚拟和保护等方面:
  • 抽象类: 会话基类TSessionBase、数据库基类TDatabaseBase均是抽象类,分别提供了数据包分析与判断、数据存储的虚拟方法;
  • 泛型类: 主要基类TSocketServerBase有TSessionBase、TDatabaseBase两个泛型约束参数,可以根据这两个抽象类的派生类产生具体的服务器类型;
  • 方法抽象(abstract): TSessionBase的数据包分析方法AnalyzeDatagram()、TDatabaseBase的数据库打开方法Open()均是抽象的,必须在派生类中根据业务处理逻辑和数据库类型重写;
  • 方法保护(protected): 与事件处理有关的方法、与业务处理逻辑相关的方法全部是protected方法,可以根据实际情况重写。

1.2 类架构

1)主要类层次结构


(图1 主要类层次关系) 按应用类别分,EMTASS主要有四组类:Socket服务器类、Session会话类、Database数据库类和枚举类型。
  • Socket服务器类
    • 服务器泛型类 TSocketServerBase: 该类包括了一个服务器Socket对象、一个TDatabaseBase派生 类对象、一个会话TSessionBase类派生对象的列表(Dictionary<>泛型对象),封装了TDatabaseBase、 TSessionBase的全部事件,提供统一的对外公开接口和事件;
    • 泛型参数: 服务器基类TSocketServerBase有两个泛型参数:TSessionBase类和TDatabaseBase类,定制它们的派生类后可以确定泛型类的具体版本。
  • 客户端会话类
    • 会话核心成员类 TSessionCoreInfo: 是TSessionBase的基类,包括会话的核心字段:登录时间、最近会话时间、IP地址、客户端名、对象状态等,是会话列表清单和事件参数的基类之一。该类的成员字段全部是protected的,需要在派生类中赋予具体值;
    • 抽象会话类 TSessionBase: 封装了客户端Socket、数据接收缓冲区、数据包缓冲区、数据包队列等数据结构,包括了与客户端通信相关的全部方法:数据接收与发送、数据包处理等。
  • 数据库类
    • 抽象数据库基类 TDatabaseBase: 封装了数据库打开与关闭、异常事件处理等方法,其中数据连接属性DbConnection是虚属性、数据库打开方法Open()是抽象方法,需要在派生类中重写;
    • 基类TSqlServerBase: 派生自TDatabaseBase,应用System.Data.SqlClient名称空间中SqlServer相关类型重定义了数据库连接属性DbConnection、重写了Open()方法;
    • 基类TOleDbDatabaseBase: 派生自TDatabaseBase,应用System.Data.OleDb名称空间中OleDb数据访问相关类型重定义了基类的连接属性DbConnection、重写了Open()方法
  • 枚举类型
    • 会话状态类型 TSessioinState: 取4个值:Valid、Invalid、Shutdown和Closed。为Valid时表示会话是有效的,为Invalid时表示会话将被清理,为Shutdown时表示会话Socket正在卸载,为Closed时表示会话已经关闭、资源已经清理;
    • 会话断开类型 TDisconnectType: 取3个值:Normal、Timeout和Exception,分别表示正常连接、超时断开、异常断开。其中,超时表示最近两次会话接收数据的时间超过约定的时限,防止某些会话长时间占有资源。

2)事件参数类型结构图


(图2 事件参数类层次关系) EMTASS框架的事件包括三类:第一,普通事件,如:服务器启动与停止;第二,异常事件,接收与发送数据异常、数据库连接或数据存储异常 等;第三,与会话相关事件,如:增加会话对象、接收到一个合法数据包等。异常与会话结合即是会话异常事件。通过泛型委托EventHandler可以定义类事件,其中的事件参数类型如下:
  • 异常事件参数类 TExceptionEventArgs: 封装了异常Exception对象的Message值;
  • 会话事件参数类 TSessionEventArgs: 封装了一个TSessionCoreInfo对象;
  • 会话异常参数类 TSessionExceptionEventArgs: 派生自TSessionEventArgs,包括异常消息字段Message。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多