通过自定义消息:
局限:发送的数据只能是长整型。
#define WM_COMM
WM_USER+100
CWnd *pWnd=CWnd::FindWindow(NULL,_T("
DataRecv查找DataRecv进程.")); //
pWnd->SendMessage(
WM_COMM,NULL,(LPARAM)uMsg);// 发送.
const UINT wm_nRegMsg=RegisterWindowMessage("reg_data");
CWnd *pWnd=CWnd::FindWindow(NULL,_T("DataRecv")); // 查找DataRecv进程.
pWnd->SendMessage(
wm_nRegMsg,NULL,(LPARAM)uMsg);// 发送.
接受函数里
#define WM_COMM
WM_USER+100
ON_MESSAGE(WM_COMM,OnUserReceiveMsg)
const UINT wm_nRegMsg=RegisterWindowMessage("reg_data");
ON_REGISTERED_MESSAGE(wm_nRegMsg,OnRegReceiveMsg)
void CDataRecvDlg::OnUserReceiveMsg(WPARAM wParam,LPARAM lParam)
{
m_strUserMsg.Format("%d/n",int(lParam));
…………………………..
}
使用WM_COPYDATA消息:
局限:
WM_COPYDATA
不能发送
HD
C
、HBITMAP之类的东西。
发送方:
CWnd *pWnd=CWnd::FindWindow(NULL,_T("DataRecv")); // 查找DataRecv进程
COPYDATASTRUCT cpd; // 给COPYDATASTRUCT结构赋值.
cpd.dwData = 0;
cpd.cbData = m_strCopyData.GetLength();
cpd.lpData = (void*)m_strCopyData.GetBuffer(cpd.cbData);
pWnd->SendMessage(WM_COPYDATA,NULL,(LPARAM)&cpd);// 发送.
接收方:
ON_WM_COPYDATA()
afx_msg BOOL OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct);
BOOL CDataRecvDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
m_strCopyData=(LPSTR)pCopyDataStruct->lpData;
……………..
}
使用内存读写函数:
#define BUFFER_SIZE 0x100 //
用内存地址通信时分配的最大内存.
const UINT wm_nMemMsg=RegisterWindowMessage("mem_data");
void OnSendMem() {
CWnd *pWnd=CWnd::FindWindow(NULL,_T("DataRecv")); // 查找DataRecv进程.
if(pWnd==NULL){
AfxMessageBox("Unable to find DataRecv.");
return;
}
//
获取进程号
.
DWORD PID;
GetWindowThreadProcessId(pWnd->m_hWnd, (DWORD*)&PID );
HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS,FALSE,PID);
//
分配虚拟内存
.
LPVOID lpBaseAddress;
lpBaseAddress = VirtualAllocEx(hProcess, 0, BUFFER_SIZE,
MEM_COMMIT, PAGE_READWRITE);
char data[BUFFER_SIZE]; ……………………….
需要传递的数据
strcpy(data,m_strMem);
//
把字符串写入
hProcess
进程的内存
.
WriteProcessMemory(hProcess, lpBaseAddress, data, BUFFER_SIZE, NULL);
//
发送基址给
DataRecv
进程.
pWnd->SendMessage(wm_nMemMsg,NULL,(LPARAM)lpBaseAddress);
//
等待接收程序接收数据
.
Sleep(100);
//
释放虚拟内存.
VirtualFreeEx(hProcess,lpBaseAddress, 0, MEM_RELEASE);
}
接收方:
afx_msg void OnRegMemMsg(WPARAM wParam,LPARAM lParam);
void OnRegMemMsg(WPARAM wParam,LPARAM lParam){
LPVOID lpBaseAddress=(LPVOID)lParam;
HANDLE hProcess=GetCurrentProcess();
char data[BUFFER_SIZE];
ReadProcessMemory(hProcess, lpBaseAddress, data,BUFFER_SIZE, NULL);
}
使用内存映射文件:
程
A
和进程
B
之间共享如下一个
struct:
struct m_MapView_Struct{
char m_c;
int m_iMapView;
char m_pszMapView[MAX_BUFFER_SIZE];
char m_pszMapView2[MAX_BUFFER_SIZE];
}* m_pSMapView;
进程
A
中:
m_hMapObject=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,
PAGE_READWRITE, 0, 0x1000, _TEXT("shared_memory"));
f(!m_hMapObject){
AfxMessageBox("Unable to create shared memory file.");
return FALSE;
}
// Map view of file into our address space. m_pSMapView=(m_MapView_Struct *)MapViewOfFile
(m_hMapObject,FILE_MAP_WRITE, 0, 0,0);//
FILE_MAP_ALL_ACCESS
if(m_pSMapView==NULL){
AfxMessageBox("Unable to map shared memory file.");
return FALSE;
}
m_pSMapView->m_iMapView = 13628;
m_pSMapView->m_c = '*';
lstrcpy(m_pSMapView->m_pszMapView, "c++");
lstrcpy(m_pSMapView->m_pszMapView2, "stl wlt atl");
UnmapViewOfFile(…);
进程
B
中:
// Open memory mapped file.
m_hMapObject=OpenFileMapping(FILE_MAP_READ,FALSE,_TEXT("shared_memory"));//
if(!m_hMapObject){
AfxMessageBox("Can't open shared memory file,please run 'Send' first.");
SendMessage(WM_CLOSE);
return FALSE;
}
// Get pointer to shared data.
m_pSMapView=(m_MapView_Struct *)MapViewOfFile (m_hMapObject,FILE_MAP_READ, 0, 0,0);
if(m_pSMapView==NULL) //
FILE_MAP_ALL_ACCESS
AfxMessageBox("Can't map view of shared memory file.");
m_strText.Format("%d,%s,%s,%c",m_pSMapView->m_iMapView, m_pSMapView->m_pszMapView
,m_pSMapView->m_pszMapView2 ,m_pSMapView->m_c);
UnmapViewOfFile(…);
使用DLL进行通信:
// DllObj.h:
头文件.
#ifndef _DLLOBJ_H__INCLUDED
#define _DLLOBJ_H__INCLUDED
#include <afxmt.h>
#ifdef __cplusplus
#define __DLLCOM__ extern "C" __declspec (dllexport)
#else
#define __DLLCOM__ __declspec (dllexport)
#endif
__DLLCOM__
LPSTR GetValueString();
__DLLCOM__
void SetValueString(LPCSTR str);
#endif
; dllcom.def : Declares the module parameters for the DLL.
LIBRARY "dllcom"
DESCRIPTION 'dllcom Windows Dynamic Link Library'
EXPORTS
; Explicit exports can go here
dllcom.cpp
#pragma data_seg
("SHARED")
char
m_strString[256]=TEXT("");
volatile bool
bInCriticalSection=FALSE;
#pragma data_seg
()
#pragma comment
(linker,"/SECTION:SHARED,RWS")
CCriticalSection
cs;
//
从内存中读取字符串
.
__DLLCOM__
LPSTR GetValueString()
{
while(bInCriticalSection) //
等待
.
Sleep(1);
return m_strString;
}
//
把字符串存储到共享内存中
.
__DLLCOM__
void SetValueString(LPCSTR str)
{
while(bInCriticalSection) //
等待
.
Sleep(1);
cs.Lock();
bInCriticalSection = TRUE;
strcpy(m_strString,str);
bInCriticalSection = FALSE;
cs.Unlock();
}
使用剪切板进行通信:
//
打开系统剪贴板
.
if (!OpenClipboard()) return;
//
使用之前,清空系统剪贴板
.
EmptyClipboard();
//
分配一内存,大小等于要拷贝的字符串的大小,返回的内存控制句柄
.
HGLOBAL hClipboardData;
hClipboardData = GlobalAlloc(GMEM_DDESHARE, strData.GetLength()+1);
//
内存控制句柄加锁,返回值为指向那内存控制句柄所在的特定数据格式的指针
.
char * pchData;
pchData = (char*)GlobalLock(hClipboardData);
//
将本地变量的值赋给全局内存
.
strcpy(pchData, LPCSTR(strData));
//
给加锁的全局内存控制句柄解锁
.
GlobalUnlock(hClipboardData);
//
通过全局内存句柄将要拷贝的数据放到剪贴板上
.
SetClipboardData(CF_TEXT,hClipboardData);
//
使用完后关闭剪贴板
.
CloseClipboard();
接收方:
//
打开系统剪贴板
.
if (!OpenClipboard()) return;
//
判断剪贴板上的数据是否是指定的数据格式
.
if (IsClipboardFormatAvailable(CF_TEXT)|| IsClipboardFormatAvailable(CF_OEMTEXT))
{
//
从剪贴板上获得数据
.
HANDLE hClipboardData = GetClipboardData(CF_TEXT);
//
通过给内存句柄加锁,获得指向指定格式数据的指针
.
char *pchData = (char*)GlobalLock(hClipboardData);
//
本地变量获得数据
.
m_strClipBoard = pchData;
//
给内存句柄解锁
.
GlobalUnlock(hClipboardData);
}
else
AfxMessageBox("There is no text (ANSI) data on the Clipboard.");
//
使用完后关闭剪贴板
.
CloseClipboard();
一下方法既可以用于本地系统上进程间通信,也适用于远程不同系统上进程间通信。
使用命名管道进行进程间通信:
命名管道最适合两个进程间的消息传递,如果进程不知道这个管道名就不能取走数据。一方接收到数据之后可以立即通知另一方。
// MyPipe.h:
定义
CMyPipe
类
.
#ifndef _MYPIPE_H__INCLUDED
#define _MYPIPE_H__INCLUDED
class CMyPipe
{
public:
CMyPipe();
virtual ~CMyPipe();
public:
static UINT ServerReadProc(LPVOID lpVoid);
void ServerCreateNamedPipe(CString strReply);
void ClientSend(CString strRequest);
int ClientCreateFile();
void ServerClose();
void ClienClose();
CString GetReply() { return m_strReply;}
CString GetRequest() { return m_strRequest;}
private:
CWinThread *m_pThread;
CString m_strReply;
CString m_strRequest;
HANDLE m_hPipe;
};
#endif
// MyPipe.cpp:
实现
CMyPipe
类
.
#include "stdafx.h"
#include "MyPipe.h"
CMyPipe::CMyPipe()
{m_pThread=NULL;}
CMyPipe::~CMyPipe()
{
if(m_pThread){
if(TerminateThread(m_pThread->m_hThread,0))
{
if(m_pThread)
delete m_pThread;
m_pThread = NULL;
}
}
}
int CMyPipe::ClientCreateFile()
{
LPCSTR szPipeName=TEXT("////.//pipe//ssnp//");
if (WaitNamedPipe( szPipeName, NMPWAIT_WAIT_FOREVER)==FALSE ){
AfxMessageBox(_T("No existing Pipe can use now"));
TRACE("No existing Pipe can use now. Error: %d/n",GetLastError());
return 0;
}
m_hPipe=CreateFile(szPipeName,
GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ| FILE_SHARE_WRITE,NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_ARCHIVE|FILE_FLAG_WRITE_THROUGH,
NULL);// FILE_FLAG_WRITE_THROUGH
设定阻塞
.
//
检查并判别命名管道文件是否被打开
,
如果没有被打开,终止程序
.
if (m_hPipe == INVALID_HANDLE_VALUE){
TRACE("Unable to create a named pipe. Error: %d/n",GetLastError());
return 0;
}
return 1;
}
//---------------------------------------------------------------------------
//
用于客户程序的函数
.
void CMyPipe::ClientSend(CString strRequest)
{
m_strRequest=strRequest;
char toSendtxt[80];
//
反复发送消息直到程序终止
.
while(1)
{
TRACE("Sending.../n");
DWORD dwNumBytesWritten,dwNumBytesRead;
strcpy(toSendtxt,m_strRequest);
//
向管道写入消息
.
if (!WriteFile(m_hPipe,toSendtxt,(DWORD)sizeof(toSendtxt),&dwNumBytesWritten,(LPOVERLAPPED) NULL)){//
如果向命名管道写入时出现错误
,
终止程序
.
TRACE("Unable to write to named pipe. Error: %d/n",GetLastError());
CloseHandle(m_hPipe);
}
else{ //
如果向管道写入消息成功,则执行下面代码
ReadFile(m_hPipe,toSendtxt, (DWORD)sizeof(toSendtxt),
&dwNumBytesRead,(LPOVERLAPPED) NULL);
m_strReply=toSendtxt;
break;
}
//
在再次发送消息前等待
.
Sleep(4800);
}
}
//---------------------------------------------------------------------------
//
用于服务程序的函数
.
void CMyPipe::ServerCreateNamedPipe(CString strReply) {
m_strReply=strReply;
LPCSTR szPipeName=TEXT("////.//pipe//ssnp//");
//
为接收消息创建命名管道
.
m_hPipe=CreateNamedPipe(szPipeName,
PIPE_ACCESS_DUPLEX|FILE_FLAG_WRITE_THROUGH,
//
阻塞模式
.
PIPE_WAIT|PIPE_TYPE_BYTE,PIPE_UNLIMITED_INSTANCES, 128,128,NULL,NULL);
//
检查是否命名管道被创建
.
if (m_hPipe == INVALID_HANDLE_VALUE){
TRACE("Unable to create a named pipe./n");return;
}
m_pThread=AfxBeginThread(ServerReadProc, this); //
启动线程
.
}
//---------------------------------------------------------------------------
UINT CMyPipe::ServerReadProc(LPVOID lpVoid)
{
DWORD dwNumBytesRead,dwNumBytesWrite;
char toDisptxt[80];
//
允许客户连接命名管道
,
如果不成功,终止
.
TRACE("Waiting for connection... /n");
CMyPipe *Parent= (CMyPipe*)lpVoid;
if(!ConnectNamedPipe(Parent->m_hPipe, (LPOVERLAPPED) NULL)){
TRACE("Unable to connect a named pipe. Error: %d/n",GetLastError());
CloseHandle(Parent->m_hPipe);
return 1;
}
//
反复检查消息直到程序终止
.
while(1)
{
//
读取消息并检查读取数据是否成功
.
if (!ReadFile(Parent->m_hPipe, toDisptxt,sizeof(toDisptxt),&dwNumBytesRead, (LPOVERLAPPED) NULL)) {
TRACE("Unable to read from named pipe. Error: %d/n" ,GetLastError());
CloseHandle(Parent->m_hPipe);
//return 1;
}
else{//
如果
ReadFile
成功,则执行下面代码
//
保存接收的字符串
.
Parent->m_strRequest=toDisptxt;
strcpy(toDisptxt,Parent->m_strReply);
//
写回一个字符串
.
WriteFile(Parent->m_hPipe, toDisptxt,sizeof(toDisptxt),
&dwNumBytesWrite, (LPOVERLAPPED) NULL);
}
}
return 0;
}
void CMyPipe::ServerClose()
{
DisconnectNamedPipe(m_hPipe);
CloseHandle(m_hPipe);
return;
}
void CMyPipe::ClienClose()
{
//CloseFile();
return;
}
使用邮槽进行进程间通信:
邮槽适合一个进程向多个进程广播消息,其存储的数据可以任何形式,但大小不能超过64K。
当邮槽的所有句柄都关闭后,该邮槽及其中的数据就被删除。邮槽通信是
单向UDP发送数据,所以发送前没有建立一个可靠的连接。的,客户端只能写,服务器端只能读。使用
// MyMailSlots.h:
定义
CMyMailSlots
类
.
#ifndef _MYMAILSLOTS_H__INCLUDED
#define _MYMAILSLOTS_H__INCLUDED
class CMyMailSlots
{
public:
CMyMailSlots();
virtual ~CMyMailSlots();
public:
static UINT ServerReadProc(LPVOID lpVoid);
void ServerCreateMailslot();
void ClientCreateFile();
void ClientSend(CString strRequest);
// CString GetReply() { return m_strReply;}
CString GetRequest() { return m_strRequest;}
private:
// CString m_strReply;
CString m_strRequest;
HANDLE m_hSMS_Slot;
CWinThread *m_pThread;
};
#endif
// MyMailSlots.cpp:
实现
CMyMailSlots
类
.
#include "stdafx.h"
#include "MyMailSlots.h"
CMyMailSlots::CMyMailSlots()
{
m_pThread = NULL;
}
CMyMailSlots::~CMyMailSlots()
{
if(m_pThread){
if(TerminateThread(m_pThread->m_hThread,0)){
if(m_pThread)
delete m_pThread;
m_pThread = NULL;
}
}
}
void CMyMailSlots::ClientCreateFile()
{
LPCSTR szMailslotName= TEXT("////.//mailslot//sms");
//
为发送消息创建
mailslot
文件句柄
.
m_hSMS_Slot=CreateFile(szMailslotName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ| FILE_SHARE_WRITE,NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_ARCHIVE|FILE_FLAG_WRITE_THROUGH,
// FILE_FLAG_WRITE_THROUGH
设定阻塞
.
NULL);
//
检查
mailslot
文件是否打开
,
如果如果没有打开
,
终止程序
.
if (m_hSMS_Slot == INVALID_HANDLE_VALUE)
TRACE("Unable to create mailslot. Error: %d/n", GetLastError());
}
//
用于客户程序的函数
.
void CMyMailSlots::ClientSend(CString strRequest)
{
DWORD bufferLen=100;
BOOL bStatus;
DWORD dwNumBytesWritten;
m_strRequest=strRequest;
char toSendTxt[100];
//
生成发送的字符串
.
strcpy(toSendTxt, strRequest);
TRACE("Sending.../n");
//
向
mailslot
写入信息
.
bStatus=WriteFile(m_hSMS_Slot,toSendTxt, (DWORD) sizeof(toSendTxt),&dwNumBytesWritten, (LPOVERLAPPED) NULL);
if (!bStatus){
TRACE("Unable to write to mailslot. Error: %d/n",GetLastError());
CloseHandle(m_hSMS_Slot);
}
}
//
用于服务程序的函数
.
void CMyMailSlots::ServerCreateMailslot()
{
LPCSTR szMailslotName= TEXT("////.//mailslot//sms");
//
为接收消息创建
mailslot.
m_hSMS_Slot=CreateMailslot(szMailslotName,0,0,(LPSECURITY_ATTRIBUTES) NULL);
//
检查
mailslot
是否被创建
if (m_hSMS_Slot == INVALID_HANDLE_VALUE){
TRACE("Unable to create mailslot. Error: %d/n",GetLastError());
return;
}
m_pThread=AfxBeginThread(ServerReadProc,this); //
启动线程
.
}
UINT CMyMailSlots::ServerReadProc(LPVOID lpVoid)
{
DWORD dwNextSize;
DWORD dwMsgs;
DWORD dwNumBytesRead;
BOOL bStatus;
char toDisptxt[100];
CMyMailSlots* Parent=(CMyMailSlots*)lpVoid;
//
反复检查消息直到程序终止
.
while(1){
bStatus=GetMailslotInfo(Parent->m_hSMS_Slot,(LPDWORD) NULL, &dwNextSize, &dwMsgs,
(LPDWORD) NULL);
if (!bStatus){
TRACE("Unable to get status. Error:%d/n",GetLastError());
CloseHandle(Parent->m_hSMS_Slot);
return 1;
}
TRACE("%d/n",dwNextSize);
//
如果有消息
,
获取它
.
if (dwMsgs&&dwNextSize!=-1){
//
读取消息并检查读取是否成功
.
if (!ReadFile(Parent->m_hSMS_Slot, toDisptxt, dwNextSize,
&dwNumBytesRead, (LPOVERLAPPED) NULL)){
TRACE("Unable to read from mailslot. Error: %d/n",GetLastError());
CloseHandle(Parent->m_hSMS_Slot);
return 1;
}
else{
Parent->m_strRequest=toDisptxt; //
保存消息
.
}
}
else
Sleep(500); //
每秒钟两次检查新消息
.
}
return 0;
}
From: http://blog.csdn.net/boyplayee/archive/2007/03/09/1525079.aspx