AD
AD

Visual C++进程间数据通信的实现

时间:2007-12-26 23:47:57  来源:  作者:
AD
  在Windows系统中,各个应用/doc/">程序(进程)之间常常需要交换、传递数据,这就要解决进程间的数据通信问题。在最初的16位Windows3.x系统中,所有Windows应用/doc/">程序共享单一地址,任何进程都能够对这一共享地址空间的数据进行读写操作。随着Windwos98、WindowsNT、Windows2000等32位的操作系统的出现,规定每个进程都有自己的地址空间,一个Windows进程不能存取另一个进程的私有数据,也就是说,虽然两个进程可以用具有相同值的指针寻址,但所读写的只是它们各自的数据,这样就减少了进程之间的相互干扰。那么上述技术的采用是否意味着各个应用/doc/">程序之间不能进行数据交换了呢?答案当然是否定的,强大的Windows系统早已为我们设计了很多方案来解决进行间的通信问题,这里我们只探讨如何通过动态数据交换(DDE)方法实现进程间的数据通信。

  本实例/doc/">程序功能如下,服务器端有两个数据项,一个是输入的字符串,另一个是定时增加的整数。运行该/doc/">程序的两个实例后,两个/doc/">程序就可以建立DDE连接,实现数据的传递,并将另外一个实例传送过来的数据显示出来。下图为/doc/">程序编译运行后的效果图:

字串1


图一、DDE方法实现进程间数据通信/doc/">程序的界面效果图

  一、实现方法

  自从微软推出Windows操作系统以来,动态数据交换(DDE)就已经成为Windows的部分,并且很多Windwos应用/doc/">程序都使用了DDE技术来实现进程之间的数据交换。DDE是建立在Windows内部消息系统、全局和共享全局内存基础上的一种协议,用来协调Windows应用/doc/">程序之间的数据交换和命令调用,它已经成为应用/doc/">程序之间通信的一种常用方法。

  DDE应用/doc/">程序可以分为四种类型:客户类型、服务器类型、客户/服务器类型和监视器。DDE会话发生在客户应用/doc/">程序和服务器应用/doc/">程序之间。客户应用/doc/">程序从服务器应用/doc/">程序请求数据或服务,服务器应用/doc/">程序响应客户应用/doc/">程序的数据或服务请求。客户/服务器应用/doc/">程序是既可以发出请求,又可以提供信息,监视器应用/doc/">程序则是用语调试的目的。

  DDE协议使用三级树型命名:服务(SERVICE)、主题(TOPIC)和数据项(ITEM)来标识DDE所要传送的数据单元。服务使应用/doc/">程序具有了提供给其他/doc/">程序的数据交换能力;主题类似于目录,是建立会话连接的参数:ITEM才是DDE具体通信时要传送的数据内容,比如一个数据或一个字符串。

字串3



  动态交换管理库(DDEML)提供了DDE和应用/doc/">程序级协议。使用DDEML开发的应用/doc/">程序无论是在运行一致性方面还是在应用/doc/">程序相互通信方面性能均优于没有使用DDEML的应用/doc/">程序。而且DDEML的应用使得开发支持DDE的应用/doc/">程序容易了许多。

  建立DDE会话后,客户/doc/">程序和服务器/doc/">程序可以通过三种链接方式进行数据交换,分别是:1、冷链接:客户/doc/">程序申请数据,服务器/doc/">程序立即给客户/doc/">程序发送数据;2、温链接:服务器/doc/">程序通知客户/doc/">程序数据数据项发生了改变,但是并没有将已发生的值发送给客户/doc/">程序。3、热链接:当数据项发生变化时,服务器/doc/">程序立即把变化后的值发送给客户/doc/">程序,这是最常用、最方便的方法,下面的例子就使用的这种方法。

  DDE会话初始化

  使用API函数DdeInitialize(),在DDEML中注册应用。

  会话建立

  服务器:注册服务DdeNameService.

  客户:连接DdeConnect.

  会话过程

  类似于Windows的消息循环,会话的过程就是事务处理的过程。客户通过DdeClientTransaction()来发出事务请求,通过DDE回调函数,服务器处理客户事务请求,返回DdeCreateDataHandle来发送数据,同时客户可以调用DdeGetData()获取数据。

字串6



  会话结束

  可由服务方或客户方来终止会话,推出/doc/">程序时要注消服务,释放资源,调用DdeUninitialize()。

  二、/">编程步骤

  1、启动Visual C++6.0,新建一个基于对话框的MFC应用/doc/">程序,取名为DDEdemo,添加两个Group Box/com/">控件并分别在其上放置编辑/com/">控件IDC_EDIT、静态/com/">控件ID_STATIC1、ID_STATIC2、 ID_STATIC3,用Wizard添加对应成员变m_edit(CString类型),添加并将其Caption置空,最后的界面如图一所示;

  2、使用CLASSWIZARD添加对话框函数,分别为WM_DESTORY、WM_INITDIALOG、WM_TIMER及IDC_EDIT的EN_CHANGE消息建立对应函数;

  3、在DDEdemoDlg.CPP中加入#include "ddel.h"以使用DDEML函数。并添加以下宏定义和全局变量:

#define NITEM 2 //定义ITEM的数量;
const char szApp[]="Server"; //server DDE服务名;
const char szTopic[]="Topic";//Server DDE目录名;
const char *pszItem[NITEM]={"Item1","Item2"};//SERVER ITEM名称字符串数组; 字串6
int count=0;//记数,在Static1中显示;
CString ServerData[NITEM];//存放服务器中的数据项内容;
HCONV hConv=0; //会话句柄;
DWORD idlnst=0; //DDEML实例句柄;
HWND hWnd; //窗口句柄;
HANDLE hlnst; //实例句柄;
HSZ hszApp=0; //SERVER服务字符串句柄;
HSZ hszTopic=0; //SERVER目录字符串句柄;
HSZ hszItem[NITEM]; //Server ITEM字符串句柄;
BOOL bConnect; // 建立连接标志;


   4、输入代码,编译运行/doc/">程序。


  三、/doc/">程序代码

//////////////////////////////////////DDE回调函数;
HDDEDATA CALLBACK DdeCallback(UINT wType,UINT wFmt,HCONV hConv,HSZ Topic,HSZ Item,
HDDEDATA hData,DWORD lData1,DWORD lData2)
{
 int I ;
 char tmp[255];
 switch(wType)
 {
  case XTYP_ADVSTART:
  case XTYP_CONNECT://请求连接;
   return ((HDDEDATA)TRUE);//允许;
  case XTYP_ADVDATA: //有数据到来; 字串7
   for(I=0;I<NITEM;I++)
    if(Item==hszItem[I])
    {
     DdeGetData(hData,(PBYTE)tmp,255,0);//取得数据;
     switch(I)
     {
      case 0:
       SetDlgItemText(hWnd,IDC_STATIC2,tmp);
       break;
      case 1:
       SetDlgItemText(hWnd,IDC_STATIC3,tmp);
       break;
     }
    }
   return ((HDDEDATA)DDE_FACK);//回执;
  case XTYP_ADVREQ:
  case XTYP_REQUEST://数据请求;
   for(I=0;I<NITEM;I++)
    if(Item==hszItem[I])
     return(DdeCreateDataHandle(idlnst,(PBYTE)(LPCTSTR)ServerData[I],
       ServerData[I].GetLength()+1,0,Item,wFmt,0));
 }
 return(0);
}

///////////////////////////////////////////////////// CddedemoDlg.cpp
CDdedemoDlg::CDdedemoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDdedemoDlg::IDD, pParent)
{
 //{{AFX_DATA_INIT(CDdedemoDlg)
  m_edit = _T("");
 /

文章评论

共有 0位编程爱好者发表了评论 查看完整内容

    评论加载中…