转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
用Delphi建立通讯与数据交换服务器—Transceiver技术剖析(下)         ★★★★

用Delphi建立通讯与数据交换服务器—Transceiver技术剖析(下)

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1728 更新时间:2009/4/23 18:35:24
Delphi建立通讯与数据交换服务器—Transceiver技术剖析(下) 作者:火鸟 redbirdli@hotmail.com 二、           Transceiver Service详解 1.Transceiver Service分析概要 Transceiver Service是Transceiver系统的核心构成,Transceiver Kernel负责从系统配置库读取Transceiver Console设定的Port、Channel定义与参数,运行时动态创建和管控通讯Port及其关联关系,对数据的收、发、缓冲进行调度、对日志、队列进行管理等。Transceiver Shell则是所支持全部类型的用于数据收发的Port的实现。 2.Transceiver Service设计概要 Transceiver Service是由Delphi中Service Application开发而成,Service Application可运行于系统态而非用户态,由操作系统Service Control Manager (SCM)负责程序的运行管理,Service没有用户界面,属于系统的后台程序。Transceiver Kernel是Transceiver类的一系列对Transceiver Shell建立和控管的方法,而Transceiver Shell则是一系列负责通讯的对象集合。 注:由于性能和负载的考虑,Transceiver Kernel只是从逻辑上实现上架构图中的功能划分,构成模块并未以完全对象化的方式实现。 3.Transceiver Service实现概要                        i.              建立一个Service Application 从Delphi主菜单File中选择NEW|Other…在弹出的New Items对话框中选择NEW|Service Application ,可以看到生成的程序框架如下: program Project1; uses   SvcMgr,   Unit1 in ''''Unit1.pas'''' {Service1: TService}; {$R *.RES} begin   Application.Initialize;   Application.CreateForm(TService1, Service1);   Application.Run; end.     unit Unit1; interface uses   Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs; type   TService1 = class(TService)   private     { Private declarations }   public     function GetServiceController: TServiceController; override;     { Public declarations }   end; var   Service1: TService1; implementation {$R *.DFM} procedure ServiceController(CtrlCode: DWord); stdcall; begin   Service1.Controller(CtrlCode); end; function TService1.GetServiceController: TServiceController; begin   Result := ServiceController; end; end. 可以看到除了在uses单元引用了用于服务管理的SvcMgr、TService1继承自TServiced而非TForm及一个重载的GetServiceController函数和以stdcall方式调用的ServiceController过程之外,用Delphi建立一个服务程序并没有太多特别之处,Delphi Fans也许又要欢呼了,这就是Delphi RAD的强大迷人之处。另外,Service Application由于无法直接在运行时调试,也没有用户界面,开发时应考虑调试信息的无界面输出以利于调试排错。                      ii.              创始满足特定需求的Port类 要使用运行处理机制统一的Transceiver Kernel,就要求Transceiver Shell中的Port有统一的处理规则,Shell中有些Port是Delphi开发环境中已有的组件类(如TCP、FTP等),而有些则不是(如MSMQ、File等)这时就需要自己动手建立一个可以满足需要的类。如: type//由于没有用户界面,所以继承自TComponent而非TControl    TFilePort=class(TComponent)    private        FilePath:string;//获取或保存文件的文件夹位置        Prefix:string;//文件前缀        suffix:string;//文件后缀    end; 建立TFilePort类以后,Transceiver Kernel就可以使用统一的类处理方式引用和管理对象,达到从FilePath指定的文件夹下存取特定文件的目的。如果用于信源(Source),将从特定文件夹下获取满足条件的文件,如果用于信宿(Target),将把从相应信源(Source)得到的数据写入到指定文件中(事实上每一个Port对象的实际参数都来源于系统配置库中Port表的定义)。 另一个例子: type    TCOMPort=class(TComponent)    private        ComFace:string;//获取或提交数据的COM接口    end; TCOMPort将用于从指定COM组件接口中获取数据或将数据提交到指定的COM组件接口上进行后续处理。在Delphi中OleVariant类是实现COM组件调用的途径之一,使用TCOMPort类的必要性在于,Transceiver在必要的数据存取时才会将TCOMPort定义的COM接口实例化为OleVariant对象,使用结束即释放对象,这样能减少Transceiver和COM服务器的负载压力。其它类似组件也有相同考虑。作者此处的类举例只是一种模型,必要时应加入适当的方法与事件。在开发中作者实现的类有:TCOMPort、TMSMQPort、TDBPort、TFilePort等                            iii.              多Channel的支持—声明Port的对象数组 Transceiver把一个通讯过程看作是源(Source)到目标(Target)的数据流过程,这样一个过程是Transceiver中的一个Channel,而这个Channel又是由至少两个Port构成的(一个用于Source,一个用于Target),所以要定义不定数量并且Source、Target自由组合的多个Channel,必须分别声明用于Source 和Target 的多种Port类的对象数组(并为他们建立对应的关联关系,稍后您将看到)。如:   private     { Private declarations } TCPSource:array of TServerSocket;// 用于TCP Source的对象数组 TCPTarget:array of TClientSocket;//用于TCP Target的对象数组     MailSource:array of TIdPOP3;  //用于Mail Source的对象数组 MailTarget:array of TIdSMTP;  //用于Mail Target的对象数组 fileSource:array of TFilePort;   //用于File Source的对象数组     fileTarget:array of TFilePort;   //用于File Target的对象数组     comSource:array of TCOMPort;//用于COM Source的对象数组 comTarget:array of TCOMPort; // 用于COM Target的对象数组 注:由于同一类型的用于Source和Target的Port运行规则的也完全不同,在Transceiver概念中被视为是完全不同并且无直接关系的对象。所以同一类型的Port,对象数组也按Source和Target分别建立。                           iv.              运行时实例化对象数组 每一个对象数组的元素个数由Port Builder在运行时管理,如果用户通过Transceiver Console定义了一些某种类型的Port,Port Builder将按照其个数和各自参数实例化该对象数组。否则,该对象数组将不会被实例化。在Source类型的Port对象中,Name属性被设置为''''Receive''''+Port ID 的形式,在之后的数据接收触发中,这将有助于Data Dispatcher定位对象和对不同类型的Port对象进行统一调度。Tag属性被用来向Channel Controller提供其所在Channel的target ID信息。 以下是Port Builder中对comSource对象数组的实例化部分      begin //Create COM/ Receive Port        itmp:=high(comSource)+1; // 获取comSource的当前最大个数,itmp为integer变量 SetLength(comSource,itmp+1); // 添加一个comSource数组成员        comSource [itmp]:=TCOMPort.Create(self);// 实例化成员 comSource[itmp].Name:= ''''Receive''''+inttostr(isource); //设置Name属性为''''Receive''''+Port ID,isource为整型的当前PortID        comSource [itmp].Tag:= itarget;//设置为其所在Channel的target ID        NullTest:=rece.Fields[''''Address''''].value; //得到系统配置COMFace的值,NullTest为Variant变量        if (NullTest <>null) and (trim(NullTest)<>'''''''') then              begin comSource [itmp].ComFace:=NullTest; //将有效值赋与ComFace NullTest:=rece.Fields[''''interval''''].value; //得到系统配置中COM对象获取数据的触发时间间隔 SetTimer(application.handle,isource,NullTest*60000,nil); //为当前Port建立用于定时收取数据的触发时钟, isource为Port ID end else  comSource [itmp].Tag:=-1;//初始化失败,标识为无效Port     end; comSource是用于在一定的时间间隔后对ComFace中定义的接口进行调用并获取数据的Source类Port,相应comTarget的实现与其类似,只是由于向comTarget的ComFace提交数据是一个实时过程,所以不需要用到触发间隔,省略建立时钟的两条语句即可。其它类型的Port对象创建和初始化大同小异。如,另一个MailTarget实现片段:               begin //Create SMTP/Send Port                 itmp:=high(MailTarget)+1;                 SetLength(MailTarget,itmp+1);                 MailTarget[itmp]:=TIdSMTP.Create(self);                 MailTarget[itmp].Name:=’send’+ inttostr(itarget);                 MailTarget[itmp].Tag:=3;// 设置为Target Port类型标识                 NullTest:=rece.Fields[''''Address''''].value; //邮件服务器地址                 if (NullTest <>null) and (trim(NullTest)<>'''''''') then                                         MailTarget[itmp].Host :=NullTest  else  bValid:=false;                 NullTest:=rece.Fields[''''Port''''].value; //邮件服务器端口                 if NullTest <>null  then  (if NullTest<>0 then MailTarget[itmp].Port :=NullTest)  else  bValid:=false;                 NullTest:=rece.Fields[''''user''''].value;//登录用户名                 if NullTest <>null then  MailTarget[itmp].UserId :=NullTest else  bValid:=false;                 NullTest:=rece.Fields[''''password''''].value;//登录口令                   ……………                                  ……………               end; 或许你会有这样的疑惑,大量的Transceiver Shell通讯组件在运行时被Port Builder创建,Transceiver Service的性能会高吗?事实上,Port Builder的使命是在ServiceCreate事件发生时一次性完成的,Shell Port的数目只会影响Transceiver Service的初始化速度,Shell Port的通讯速度和Transceiver Servicer的整体性能将不受影响,当然系统资源可能会占用更多一些。                             v.              事件的动态分配和处理 在Transceiver Shell所支持的若干种通讯Port当中,使用TServerSocket(可能您更倾向于使用Indy的通讯组件,但这并不违背Transceiver Service的设计思想,只是Shell层面的修改或增加而已)实现的TCPSource是比较有特点的一种,因为TServerSocket作为一种Source Port,不同于COM或POP3之类需要定时触发的对象,它是在Transceiver Service启动后时刻处于监听状态,当有ClientSocket连接并发送数据时产生相应事件的组件。以下是TCPSour

[1] [2]  下一页


[Delphi程序]用Delphi建立通讯与数据交换服务器—Transceiver技…  
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台