进程间通信
来源:互联网 发布:开通58端口有什么用 编辑:程序博客网 时间:2024/05/17 04:38
通过自定义消息:
局限:发送的数据只能是长整型。
#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不能发送HDC、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
- 进程&进程间通信
- 信号通信(进程间通信)
- 进程间通信-管道通信
- 进程间通信--管道通信
- [进程通信] 进程间通信 之 管道
- 进程与进程间通信
- 【IO进程】进程间通信
- 进程间通信
- 进程间通信方式
- 进程间通信IPC
- 进程间通信
- 操作系统:进程间通信
- 进程间的通信
- 进程间通信
- 进程间通信IPC
- 进程间通信
- 进程间通信总结
- 进程间管道通信
- 利用Java实现串口全双工通讯
- Lpc系列ARM的中断向量表中实现方式
- 入党谈话内容
- 老师傅的话:人要有一双慧眼,去发现去寻找!
- *空间风格公布!
- 进程间通信
- gcc与g++
- c# 中使用构构函数与IDisposable接口双重释放资源
- nameQuery异常解决方案(转自网络)
- GRUB入门和技巧:通过Windows XP安装GRUB到MBR区,并且使用中文菜单!
- 双系统重装(XP+Linux)小结
- hibernate绑定参数类型[ZT](转自网络)
- 类的常量
- [转]新员工上班前后分别与老板的对话