利用动态库技术进行通信协议模块化设计

来源 :电脑知识与技术 | 被引量 : 0次 | 上传用户:ouyang
下载到本地 , 更方便阅读
声明 : 本文档内容版权归属内容提供方 , 如果您对本文有版权争议 , 可与客服联系进行内容授权或下架
论文部分内容阅读
  摘要:该文针对利用动态库技术进行通信协议模块化设计进行研究,首先简要地介绍了动态库基本理论,然后给通信协议动态库设计方法和设计要点,最后给出了基于UDP的通信协议动态库开发实例。
  关键词:动态库
  中图分类号:TP393 文献标识码:A 文章编号:1009-3044(2015)09-0058-03
  在设计通信程序时,在其程序的实现形式上主要分为可执行应用程序和动态链接库。前者能够独立运行,通常针对某一特定需求而使用,功能完备但可移植性不强;后者不能独立运行,只是以库的形式提供相关功能的函数、类及其他数据,动态库可以为某一特定需求而定制。
  利用动态库技术进行通信协议设计,按照从核心到外围的层次关系进行模块化组合设计,各模块动态加载,可扩展,独立编译,软件系统层次明确、内外松散耦合,便于功能组合和升级改造,提升软件质量。
  1 动态库基本理论
  1.1动态库分类
  VC支持三种DLL,它们是:
  1)Non-MFC DLL:指的是不用MFC的类库结构,直接用C语言写的DLL,其输出函数一般用的是标准C接口,并能被非MFC或MFC编写的应用程序所调用。
  2)Regular DLL:和下述Extension DLL一样,是用MFC类库编写的,能够被所有支持DLL技术的语言所编写的应用程序调用。在这种动态链接库中,它必需有一个从CWinAPP继承下来的类,DLLMain函数被MFC提供,不用自己显式的写出来。
  3)Extension DLL:只被用MFC类库所编写的应用程序所调用。在这种动态链接库中,用户可以从MFC继承想要的、更适于自己用的类,并把它提供给自己的应用程序。与Regular DLL不一样,它没有一个从CWinAPP继承下来的类的对象,用户必需为自己的DLLMain函数添加初始化代码和结束代码。
  1.2 DLL调用方法
  DLL的创建是供可执行应用程序调用的。使用了外部DLL的应用程序的创建与普通应用程序的创建完全一样。在此基础上可以对外部DLL进行显式或隐式调用。对DLL的调用分为两种,一种是显式的调用,一种是隐式的调用。所谓显示的调用,是指在应用程序中用LoadLibrary或MFC提供的AfxLoadLibrary显示地将自己所做的动态库调进来,动态链接库的文件名即是上面函数的参数,再用GetProcAddress获取想要引入的函数。自此,就可以像使用应用程序自定义的函数一样来调用此引入函数了。在应用程序退出之前,应该用FreeLibrary或MFC提供的AfxFreeLibrary釋放动态链接库。
  隐式的调用则需要把产生动态链接库时产生的.LIB文件加入到应用程序的工程中,想使用DLL中的函数时,只需声明一下即可,而无需调用LoadLibrary和FreeLibrary对DLL进行显示加载、卸载。
  隐式调用的方法比较简单,但隐式调用的DLL在应用程序加载的同时被加载到内存中,当应用程序调用的DLL比较多时,装入的过程十分缓慢。通过延迟加载技术可以很好地解决该问题。但除了必须的.dll文件外还需要DLL的.h文件和.lib文件。这在那些只提供.dll文件的场合就无法使用了,而只能采用显式调用方式。
  1.3 输入函数和输出函数
  模块是Windows的基本构成单元,主要由应用程序模块和DLL模块组成。这两类模块的结构是一样的,都可以“输出”(export)函数供其他模块使用,也可以“输入”(import)其他模块的函数。输入一个函数就是在代码中创建指向该函数的动态链接,而非像在静态链接中那样实际装配该函数的代码。与DLL不同,由应用程序模块输出的函数是无法为其他应用程序模块所输入的。
  MFC提供的用于输出的函数的关键字是__declspec和dllexport。在要输出的函数、类或数据的声明前使用__declspec(dllexport)表示输出。若要输出动态库中的函数mimafuwu(HWND hWnd)供应用程序输入使用则在动态库中声明该函数如下:
  #define REGULARMFCDLLLIB __declspec(dllexport)
  extern "C" REGULARMFCDLLLIB unsigned short mimafuwu(HWND hWnd);
  在应用程序输入声明如下,_cdecl为调用约定:
  unsigned short (_cdecl *Func)(HWND);
  2 通信协议动态库设计
  2.1 动态库结构
  通信协议动态库一般只包含一个输出函数和由该输出函数创建的三个UI线程(用户界面线程)即主控线程、数据接收线程和数据发送线程组成。三个线程分别对应三个模块:DLL主控模块,DLL数据接收模块和DLL数据发送模块。DLL主控模块负责与调用DLL的应用程序及DLL数据收发模块交互数据和消息,同时负责按接口协议进行解析、分包、组包、超时重传等数据处理操作,DLL数据收发模块负责与外部通信端进行物理层接口(如网口、串口等)的数据收发,DLL数据收发模块相互独立不涉及信息交互。通信协议动态库结构示意图见图1。
  2.2 动态库接口及协议
  通信协议动态库接口设计为内部接口和外部接口。如图2所示,内部接口为动态库内部模块之间的接口,外部接口有两种,分为动态库与调用其的应用程序之间的接口和动态库与外部通信端之间的接口。
  2.2.1内部接口及协议
  动态库内部接口为DLL主控模块与DLL数据发送模块之间和DLL主控模块与DLL数据接收模块之间的接口。内部模块之间主要通过自定义消息方式构造协议进行数据通信。   2.2.2外部接口及协议
  2.2.2.1 动态库和调用DLL的应用程序之间接口及协议
  动态库和调用DLL的应用程序之间接口为DLL输出函数。两者之间主要通过自定义消息方式构造协议进行数据通信。
  2.2.2.2 动态库和外部通信端之间接口及协议
  动态库和外部通信端之间的接口主要为以太网口和串口、并口等通信端口等。使用的接口协议主要有:基于TCP的网络通信协议、基于UDP的网络通信协议和基于串口/并口的端口通信协议等。
  2.3 动态库信息处理流程
  调用DLL的A端应用程序拟制一份数据按动态库和调用DLL的应用程序之间接口协议将其提交DLL主控模块,DLL主控模块按动态库和外部通信端之间接口协议进行数据处理后再按内部接口协议将数据提交DLL发送模块,DLL发送模块将数据发送到B端。DLL接收模块接收B端数据后按内部接口协议将其提交DLL主控模块,DLL主控模块按动态库和外部通信端之间接口协议收齐数据后,再按动态庫和调用DLL的应用程序之间接口协议将数据提交A端应用程序。即:
  1)A端调用DLL的应用程序->DDL主控模块->DLL发送模块- >B端
  2)B端 - >DLL接收模块->DLL主控模块->A端调用DLL的应用程序
  3 通信协议动态库设计要点
  3.1动态库中的输出函数
  应用程序一启动就应加载动态库,调用动态库输出函数。动态库中一般只有一个输出函数,该函数只负责创建UI线程。输出函数参数须包含应用程序某窗口句柄,一般为主框架窗口句柄,同时输出函数将必要的变量信息如动态库创建的某个线程的线程号回传至应用程序。通过窗口句柄和线程号作为参数,以便于应用程序和动态库之间以自定义消息的方式进行通信。
  3.2动态库中的超时时钟设置
  动态库中超时时钟的设置与应用程序有别,不能使用ON_WM_TIMER()消息机制,需采用自定义消息方式。具体方法如下。
  自定义超时消息:
  ON_MESSAGE(WM_TIMER, OnTimer)
  设置超时时钟:
  UNIT m_iTimer=::SetTimer(0,0,3000,NULL);//3000表示定时3秒
  超时消息处理函数:
  void OnTimer(WPARAM wparam,LPARAM lparam)
  {
  UINT nIDEvent =(UINT)wparam;
  if(nIDEvent==m_iTimer)
  {
  //超时处理
  }
  }
  关闭超时时钟:
  KillTimer(0,m_iTimer);
  3.3动态库与调用DLL的应用程序之间的消息传递
  如前所述,动态库与调用DLL的应用程序之间消息传递时首先需要知道应用程序窗口句柄和动态库某线程的线程号,使用的MFC消息函数如下。
  动态库往应用程序发消息:
  ::PostMessage(
  ApphWnd,
  WM_DLL_TO_APP_MSG,
  WPARAM wparam,
  LPARAM lparam);
  其中,参数ApphWnd为应用程序主框架窗口句柄,WM_DLL_TO_APP_MSG为自定义消息标识,wparam为消息中携带的参数一(如数据指针等),lparam为消息中携带的参数二(如数据长度等)。
  应用程序往动态库发消息:
  PostThreadMessage(
  m_Threadid,
  WM_APP_TO_DLL_MSG,
  WPARAM wparam,
  LPARAM lparam);
  其中,参数m_Threadid为动态库中某个线程的线程号,应用程序将消息发往该线程,WM_APP_TO_DLL_MSG为自定义的消息标识,wparam为消息中携带的参数一(如数据指针等),lparam为消息中携带的参数二(如数据长度等)。
  3.4 通信参数的设置和使用
  动态库对通信参数(诸如IP地址、端口号、串口配置,动态库路径、分包长度、固定包头、超时时钟值和重传次数等)的设置和使用一般有两种方式。一种为,读取第三方软件形成的通信参数配置文件的方式。另一种为,应用程序调用输出函数时将通信参数传递给动态库,动态库再进行通信参数的设置和使用。两种方式以前者为优。
  4 基于UDP的通信协议动态库开发实例
  结合第3节和第4节内容,本节以创建Regular DLL和显式调用DLL为例,设计一个基于UDP的通信协议动态库。为了使用该动态库,首先创建一个调用该DLL的简单应用程序。
  第一步:创建应用程序
  启动VC ,单击[File]->[New]菜单项,在project页中选择MFC AppWizard(exe),新建一个名为MyApp的基于单文档界面的工程。
  第二步:创建DLL
  1)启动VC ,单击[File]->[New]菜单项,在project页中选择MFC AppWizard(dll),新建一个名为MyLib的工程,在第一步的时候选择,创建一个动态链接MFC的规则DLL。
  2)构造输出函数mimafuwu():
  ① 在MyLib工程中填加空白源文件mimafuwu.cpp和mimafuwu.h;   ② 在mimafuwu.cpp文件中输入如下代码:
  #include "StdAfx.h"
  #include "mimafuwu.h"
  //输出函数根据具体应用而定制。
  extern "C" REGULARMFCDLLLIB unsigned short mimafuwu(HWND hWnd)
  {
  AfxMessageBox("装载DLL模块成功!");
  return 0;
  }
  ③ 在mimafuwu.h文件中输入如下代码:
  #define REGULARMFCDLLLIB __declspec(dllexport)
  //输出函数声明,输出函数根据具体应用而定制。
  extern "C" REGULARMFCDLLLIB unsigned short mimafuwu(HWND hWnd);
  3)编译后会生成库文件MyLib.dll。
  第三步:应用程序加载和使用DLL
  1)在创建的MyApp工程的MainFrm.cpp文件的函数
  CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
  return语句前添加如下代码,完成对MyLib.dll的动态链接,并完成对输出函数mimafuwu()的调用:
  //选择好MyLib.dll文件路径,装载DLL模块
  HINSTANCE hDLL = ::LoadLibrary("MyLib.dll");
  //输入函数声明
  unsigned short (_cdecl *Func)(HWND);
  // 获取函数指针
  Func = (unsigned short(_cdecl *)(HWND))::GetProcAddress(hDLL, "mimafuwu");
  //调用DLL中的函数mimafuwu(HWND)
  //同時将应用程序主框架窗口句柄传至动态库
  unsigned short nResult = Func(GetSafeHwnd());
  在上述代码中,首先由LoadLibrary()将DLL模块映射到进程的内存空间,对DLL模块进行动态加载。其函数原型为:
  LoadLibrary(LPCTSTR lpLibFileName);
  其中,参数lpLibFileName为待加载的模块名,如不特殊指定扩展名,Windows将指定默认的扩展名为“.dll”。如果成功加载则返回HINSTANCE值,标识了文件映像映射到进程地址空间的虚拟内存地址;如果加载失败则返回NULL,可通过GetLastError()了解进一步的信息。
  接下来的GetProcAddress()函数将在DLL模块中找到要输入符号的地址。其函数原型为:
  FARPROC GetProcAddress( HMODULE hModule, LPCSTR lpProcName);
  其中,参数hModule为通过LoadLibrary()等函数而得到的DLL模块句柄,lpProcName为要查找的输入符号名。GetProcAddress()在成功调用后将返回DLL的输出符号地址,否则返回空指针NULL。通过其返回得到的内存地址即可完成对输出函数的调用。
  当进程中的线程不再需要DLL中的输出符号时,可以通过AfxFreeLibrary()函数从进程的地址空间显式卸载DLL。其函数原型如下:
  BOOL FreeLibrary(HMODULE hLibModule);
  其中参数hLibModule标识了要卸载的DLL模块。
  2) 编译后会生成可执行文件MyApp.exe,确保文件MyLib.dll路径正确。运行后若弹出提示框,则应用程序加载和使用DLL成功。
  第四步:根据具体应用定制应用程序和DLL
  在前面生成的MyApp和MyLib工程的基础上进行修改。应用程序一启动就加载一个开了三个UI线程(用户界面线程)即数据接收线程、数据发送线程和主控线程的动态库,应用程序与动态库主控线程、动态库收发线程与主控线程之间通过自定义消息方式进行数据交互。在动态库库数据接收线程中创建UDP套接字,通过将IP地址设置为127.0.0.l实现应用程序对数据的自发自收。
  整个信息流程为:应用程序拟制一份数据提交动态库主控线程,动态库主控线程将收到到的数据提交动态库发送线程发送,动态库接收线程收到数据后提交动态库主控线程,动态库主控线程将数据提交应用程序,即:应用程序->DLL主控->DLL发送- >DLL接收->DLL主控->应用程序。数据在各提交过程中不做任何处理,应用程序发出的数据和收到的数据内容一致。
  5 结束语
  编写通信协议动态链接库DLL设计说明,目的是作为规范和指导DLL形式的通信协议程序模块设计工作的技术文件。同时对DLL基本程序设计、实现DLL功能扩展和对第三方提供的DLL功能模块调用等提供编程基础。利用动态库技术,遵循从核心到外围的层次关系进行模块化组合设计理念,使软件系统层次明确,各模块松散耦合、独立开发、独立验证、独立升级改造,便于整个软件系统维护与功能扩展,提升软件质量。
  参考文献:
  [1] Roberts J W. Traffic control in the BISDN[J]. Computer Networks and ISDN Systems, 1993(25): 1055-1064.
  [2] 郎锐, 孙方. Visual C 网络通信程序开发基础及实例解析[M]. 2版. 北京: 机械工业出版社, 2006.
  [3] Kruglinski D J. Visual C 技术内幕[M]. 4版. 北京: 清华大学出版社, 2009.
  [4] Ian Sommervill. 软件工程[M]. 9版. 北京: 机械工业出版社, 2011.
其他文献
摘要:微课是现代计算机互联网的新型学习资源。明确微课的含义,通过完成高职多媒体技术专业微课作品《摄影曝光基础》的设计与制作,探讨高职院校微课设计思路,高职院校微课的制作技术,高职院校微课的制作流程,以及建设高职院校微课的现实意义,从而找到一种更加科学化和规范化的适合高职院校微课教学资源的开发体系。  关键词:微课;学习资源;高职院校;微课资源开发体系  中图分类号:TP37 文献标识码:A 文章编
摘要:“数据湖”是通过将原始数据分类存储到不同数据池,并在各数据池里将数据整合转化成容易分析的统一存储格式进行存储,以方便用户对大量原始数据池中原本几近废弃的数据加以分析利用,从而产生经济效益。该文首先介绍了数据湖的结构,其次介绍了数据湖中各数据池的特点及应用;最后介绍了各数据池之间的联系并举例说明了数据湖的架构。  关键词:数据湖;数据池  中图分类号:TP391 文献标识码:A 文章编号:10
摘要:在组网工程课程教学过程中,出现专业人才培养目标定位太低,教学内容与社会需要相脱节,理论和实践教学分离等突出问题,该文针对应用型本科院校组网工程课程的教学改革提出基本思路,教学计划的修订、课程内容的增删、实践环节教学改革以及师资队伍建设等具体措施,大大提高了学生工程实践能力和创新素质。  关键词:组网工程;网络生命周期;双师型  中图分类号:G424 文献标识码:A 文章编号:1009-304
理性思维是一种有明确的思维方向,有充分的思维依据,能对事物或问题进行观察、比较、分析、综合、抽象与概括的一种思维。简言之,理性思维就是建立在证据和逻辑推理基础上的思维方式。“语文教育本质上是一种感性教育,需要语文教师具有感性的气质,充满活动和激情,还需要理性地审视,发现文本的独特价值。”事实上,小学语文课堂上,师生往往沉浸于教学情境中,在语言文字的品味与运用中不断升华情感,却往往忽视了学生理性思维
摘要:《Access 数据库》课程现如今已经成为很多高校开设的计算机基础课程,该文主要探索如何将项目教学法引入《Access 数据库》课程教学过程,最终达到良好教学效果,提高学生使用Access解决实际问题的综合能力。  关键词:项目教学法;Access数据库;教学过程  中图分类号:G642 文献标识码:A 文章编号:1009-3044(2014)31-7244-02  1 概述  随着计算机使
摘要:对于高职院校而言,公文处理工作非常重要,随着校园网络技术的发展,越来越多的高职院校都开发专门公文处理平台,关于平台的研究与实现提出了新的需求。高职院校每天要处理很多的公文文件,传统的公文流转方式己不再满足业务工作的实际需求,还停留在纸质的处理模式,导致效率低下、成本高现象。  关键词:高职院校;公文处理系统;B/S  模式中图分类号:TP315 文献标识码:A 文章编号:1009-3044(
摘要:针对当前在线课程教学和在线学习正被人们广泛接受,该文以中山中专《计算机应用基础》课在线课程的设计与应用为例,对在线课程的设计原则与设计步骤进行了探讨,提出了在线课程设计网络平台化,在线课程应用学习模块化的基本思想与应用策略。  关键词:在线课程;网络课程建设平台;教学设计;教学应用  中图分类号:G424 文献标识码:A 文章编号:1009-3044(2014)07-1454-02  近几年
摘要:受韦伯局部描述子和LBP特征的启发,针对Haar特征维度高、冗余度大以及对光照变化适应性差等缺点,提出了一种于显著性的局部二值化Haar特征。首先将8种Haar特征组合形成一个3*3的块,利用局部二值化思想得到二值化Haar特征;然后根据韦伯定律求取该块的显著性因子;最后把显著性因子作为权重将二值化Haar特征统计成直方图而得到SLBH特征。通过在INRIA行人样本库上实验,表明该特征具有较
摘要:目前量子可逆逻辑电路的绘制工作十分复杂。虽然现有的自动绘图工具只能满足基本的绘图需求,但是它们绘制出的是低分辨率的点阵图,而这种点阵图很难满足研究者们在论文发表时对高清图像的要求。因此,用C#对Visio绘图功能进行二次开发,解析并描述用户提供的量子电路TFC文件, C#读取用户对电路多种格式的自定义参数,依次画出所需的量子门,则可自动绘制出符合高清要求的矢量量子电路图。因为可逆逻辑量子电路
摘要:随着在线教育的蓬勃发展和教育大数据时代的来临,一种新型学习支持工具——学习支架应运而生。该文从学习支架的基本概念以及类型出发,分析了学习支架以不同形式在信息技术课堂中的使用情况,并结合案例分析了在教学中应该如何合理使用与教学相匹配的学习支架来提高学习者的学习能力。  关键词: 学习支架;最近发展区;信息技术  中图分类号:G43 文献标识码:A 文章编号:1009-3044(2016)34-