当前位置:首页 > VC学习笔记之二:进程通信
在头文件中添加函数声明: ??????????????? ??????????????? void SendMessage(HWND hwnd);
在CPP文件中添加函数实现
//启动发送消息
void CMessageDLLApp::SendMessage(HWND hwnd) {
::PostMessage(hwnd,WM_MSG,0,1); }
在应用程序中:
(1)在stdafx.h头文件中添加消息定义: #define WM_MSG WM_USER + 102
(2) 首先在AFX_MSG块中加入消息声明:在CTestMessageDLLDlg.h中,找到如下部分,并加入消息声明:
??????????????? ???????????????
afx_msg LRESULT OnMyMsg(WPARAM wParam,LPARAM lParam); DECLARE_MESSAGE_MAP()
(3) 在MESSAGE_MAP块中添加ON_MESSAGE宏指令: BEGIN_MESSAGE_MAP(CTestMessageDLLDlg, CDialog) ........................ ........................ ON_MESSAGE(WM_MSG, OnMyMsg) //}}AFX_MSG_MAP END_MESSAGE_MAP() (4) 添加消息函数体:
LRESULT CTestMessageDLLDlg::OnMyMsg(WPARAM wParam, LPARAM lParam) {
AfxMessageBox(\消息已经收到!\ return 0; }
(5) 在对话框上添加一个按钮,在按钮事件中,先调用DLL文件,然后发送一个测试消息响应的命令:
void CTestMessageDLLDlg::OnBnClickedButton1() {
// TODO: 在此添加控件通知处理程序代码 //定义函数
typedef void (_cdecl*STARTSENDMESSAGE)(HWND hwnd); HMODULE hmessage = NULL;
STARTSENDMESSAGE StartSendMessage = NULL; //导入DLL库文件
hmessage = LoadLibrary(\ if(hmessage==NULL) {
FreeLibrary(hmessage); exit(0); }
//导入DLL中测试消息函数 StartSendMessage =
(STARTSENDMESSAGE)GetProcAddress(hmessage,\ if(StartSendMessage==NULL) {
FreeLibrary(hmessage); exit(1); }
//获取对话框的窗口句柄
HWND hwnd = this->GetSafeHwnd(); //发送测试消息函数
(*StartSendMessage)(hwnd); }
运行应用程序,就可以看到测试结果了。
2.2.6 结论
通过上面的实例可以看出利用消息进行进程间通信不失为一种便捷的方法,进程间的数据交换量不大却能完成相当的功能,上下层次有着明显的接口,上层和底层只通过这个接口进行通讯,因此只要对上下层程序制定好规范详尽的协议便可编制出协调性很好的软件控制系统。
2.3 共享存储区
为了传送大量数据,在存储区中划出一块共享存储区,诸进程可通过对共享存储区进行
读或写数据实现通讯。
? 向系统申请共享存储区中的一个分区 ? 指定该分区的关键字
? 如果已经给其他进程分配了这样的存储区,将使用分区的描述符返回给申请者 ? 申请者将申请到的共享分区挂到本进程上 格式:
#pragma data_seg(“分区关键字”) //定义变量 #pragma data_seg()
#pragma comment(linker,\分区关键字,RWS\
比如,我们在程序头部添加了以下程序: #pragma data_seg(\int mark=0; #pragma data_seg()
#pragma comment(linker,\
为程序的单击事件添加以下代码: mark++; CString strmark;
strmark.Format(“%d”,mark); AfxMessageBox(strmark);
程序执行后,会弹出一个显示mark值的对话框,当您将这个程序运行两个实例时,操作时你会发现他们确实共享了内存。
如果是DLL程序,还可以在.def文件里加入shareddata READ WRITE SHARED来代替#pragma comment(linker,\
2.4 管道通信
管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。命名管道(Named Pipes)是在管道服务器和一台或多台管道客户机之间进行单向或双向通信的一种命名的管道。一个命名管道的所有实例共享同一个管道名,但是每一个实例均拥有独立的缓存与句柄,并且为客户——服务通信提供有
一个分离的管道。实例的使用保证了多个管道客户能够在同一时间使用同一个命名管道。 Microsoft Windows NT、Windows 2000、Windows 95以及Windows 98均提供对命名管道的支持(不包括Windows CE),但只有Windows NT和Windows 2000才支持服务器端的命名管道技术。命名管道可以在同一台计算机的不同进程之间,或在跨越一个网络的不同计算机的不同进程之间进行有连接的可靠数据通信,如果连接中断,连接双方都能立即收到连接断开的信息。命令管道是围绕Windows文件系统而设计的一种机制,采用的是命名管道文件系统(Named Pipe File System, NPFS)接口。对数据的收发也采用文件读写函数ReadFile()和WriteFile()来完成。在设计上,由于命名管道也利用了微软网络提供者(MSNP)重定向器,因此无需涉及底层的通信协议细节。命名管道还充分利用了Windows NT及Windows 2000内建的安全特性,通信的安全性相对较好。
2.4.1 管道的各种类型
管道有多种类型,如下:
1.输入管道、输出管道和双向管道: 2.字节管道或者消息管道 3.阻塞管道或者非阻塞管道 4.命名管道或者匿名管道
2.4.2 创建匿名管道
2.4.2.1 知识介绍
匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信,并且匿名管道只能单向传递信息,创建匿名管道的进程接收两个句柄:一个用于读入信息,另一个则为了写出信息。为了在进程间通信,服务器必须将句柄传递给另一进程。
匿名管道只能在父子进程之间通信,必须使用父进程调用CreateProcess启动子进程,如果两个进程单独启动那么他们并没有任何的关系。
匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句柄。CreatePipe()的函数原型为:
BOOL CreatePipe(
PHANDLE hReadPipe, //指向读句柄的指针 PHANDLE hWritePipe, //指向写句柄的指针
LPSECURITY_ATTRIBUTES lpPipeAttributes, //指向安全属性的指针 DWORD nSize //管道大小 );
通过hReadPipe和hWritePipe所指向的句柄可分别以只读、只写的方式去访问管道。在使用匿名管道通信时,服务器进程必须将其中的一个句柄传送给客户机进程。句柄的传递多
共分享92篇相关文档