词条 | 进程间通讯 |
释义 | 进程间通讯一种机制,操作系统进程和线程通过它交换数据和消息。IPC 包括本地机制(如 Windows 共享内存)或网络机制(如 Windows 套接字)。 进程间通讯进程间通讯的方式 Socket,剪切板方法,内存映射文件, 邮槽方法, 命令管道, 匿名管道方法 进程间通讯实现一、Socket的方法 对于不同机器上且数据量很的情况会有很大的帮助,但对于同一台机器之间的不同进程之间的通讯就不方便了 (代码量太多) 二、进程间通讯的剪切板方法a、对于发送端: CString str; GetDlgItemText(IDC_EDIT1,str); HANDLE hGlobal; if(this->OpenClipboard())//获取剪切板的资源所有权 { EmptyClipboard();//将剪切板的内容清空 hGlobal=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);//在堆上分配一块用于存放数据的空间,程序返回一个内存句柄 char* pBuf=(char*)GlobalLock(hGlobal);//将内存块句柄转化成一个指针,并将相应的引用计数器加一 strcpy(pBuf,str.GetBuffer(str.GetLength()));//将字符串拷入指定的内存块中 GlobalUnlock(hGlobal);//将引用计数器数字减一 ::SetClipboardData(CF_TEXT,hGlobal);//将存放有数据的内存块放入剪切板的资源管理中 ::CloseClipboard();//释放剪切板的资源占用权 } b、对于客户端 if(this->OpenClipboard())//获取剪切板的资源所有权 { HANDLE hGlobal=::GetClipboardData(CF_TEXT);从剪切板中取出一个内存的句柄 char* pBuf=(char*)GlobalLock(hGlobal);//将内存句柄值转化为一个指针,并将内存块的引用计数器加一 SetDlgItemText(IDC_EDIT2,pBuf); GlobalUnlock(hGlobal);//将内存块的引用计数器减一 CloseClipboard();//释放剪切板资源的占用权 } 三、内存映射文件方法1、 服务器端代码: HANDLE hMapFile; hMapFile= CreateFileMapping(NULL,NULL,PAGE_READWRITE,0,10,"YuanMap"); if (hMapFile == NULL) { AfxMessageBox("CreateFileMapping出错!"); return; } LPVOID pFile; pFile= MapViewOfFile(hMapFile,FILE_MAP_WRITE|FILE_MAP_READ,0,0,0); if (pFile == NULL) { AfxMessageBox("MapViewOfFile出错!"); return; } CString str; GetDlgItemText(IDC_EDIT1,str); strcpy((char*)pFile,str.GetBuffer(str.GetLength())); //CloseHandle(hMapFile); //不能加,否则客户端收不到,所以一般会将这个句柄作为一个全局变量 2、 客户机端代码: HANDLE hMap; hMap= OpenFileMapping(FILE_MAP_READ|FILE_MAP_WRITE, TRUE, "YuanMap"); LPVOID pVoid; pVoid=::MapViewOfFile(hMap,FILE_MAP_READ,0,0,0); CString str=(char*)pVoid; SetDlgItemText(IDC_EDIT1,str); UnmapViewOfFile(pVoid); CloseHandle(hMap); 四、进程间通讯的邮槽方法1、 邮槽采用的是一种广播机制。 2、 邮槽采用的是一种直接基于文件系统开发而成,所以它不依赖于某种具体的网络协议。 3、 邮槽每次传送的消息长度不能长于422字节。 4、 发送端代码如下:(客户端) HANDLE hslot; hslot=CreateFile("\\\\\\\\.\\\\mailslot\\\\myslot",GENERIC_WRITE, FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL); if(!hslot) { MessageBox("打开邮槽失败!"); return; } char *pBuf="专业的编程语言培训"; DWORD dwWrite; WriteFile(hslot,pBuf,strlen(pBuf)+1,&dwWrite,NULL); CloseHandle(hslot); 5、 接收端代码如下:(服务器端) HANDLE hMail; hMail=CreateMailslot("\\\\\\\\.\\\\mailslot\\\\myslot",0, MAILSLOT_WAIT_FOREVER,NULL); if(INVALID_HANDLE_VALUE==hMail) { MessageBox("创建邮槽失败!"); return; } HANDLE hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); OVERLAPPED ovlap; ZeroMemory(&ovlap,sizeof(ovlap)); ovlap.hEvent=hEvent; char buf[200]; DWORD dwRead; if(FALSE==ReadFile(hMail,buf,200,&dwRead,&ovlap)) { if(ERROR_IO_PENDING!=GetLastError()) { MessageBox("读取操作失败!"); CloseHandle(hMail); return; } } WaitForSingleObject(hEvent,INFINITE); MessageBox(buf); ResetEvent(hEvent); CloseHandle(hMail); 五、进程间通讯的命令管道方法A、对于发送端代码如下: HANDLE handle; handle=CreateNamedPipe("\\\\\\\\.\\\\pipe\\\\MyPipe", PIPE_ACCESS_DUPLEX,PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1,0,0,1000,NULL);//创建一个命名管道连结 ConnectNamedPipe(handle,NULL);//在命名管道实例上监听客户机连结请求 char buf[200]="http://www.it315.org"; DWORD dwWrite; WriteFile(handle,buf,strlen(buf)+1,&dwWrite,NULL);//往管道里写数据 CloseHandle(handle);//关闭管道 B、对于接收端代码如下: HANDLE hNamedPipe; WaitNamedPipe("\\\\\\\\.\\\\pipe\\\\MyPipe",NMPWAIT_WAIT_FOREVER);//等候一个命名管道实例可供自己使用 hNamedPipe=CreateFile("\\\\\\\\.\\\\pipe\\\\MyPipe",GENERIC_READ,FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//建立与命名管道的连结 char buf[200]; DWORD dwRead; ReadFile(hNamedPipe,buf,200,&dwRead,NULL);//从命名管道中读取数据 MessageBox(buf); CloseHandle(hNamedPipe);//关闭与命名管道服务器的连结 六、进程间通讯的匿名管道方法父进程: A、对于父进程中创建一个管道代码如下: SECURITY_ATTRIBUTES sa; sa.nLength=sizeof(sa); sa.bInheritHandle=TRUE; sa.lpSecurityDescriptor=NULL; if(FALSE==CreatePipe(&hRead,&hWrite,&sa,0))//创建一个匿名的管道,得到一个用于从管道读取的句柄,一个用于向管道写数据用的句柄 { MessageBox("Create pipe failed!"); return; } STARTUPINFO sui; ZeroMemory(&sui,sizeof(sui)); sui.cb=sizeof(sui); sui.dwFlags=STARTF_USESTDHANDLES; sui.hStdInput=hRead; sui.hStdOutput=hWrite; sui.hStdError=GetStdHandle(STD_ERROR_HANDLE); PROCESS_INFORMATION pi; CreateProcess("..\\\\PipeCli\\\\Debug\\\\PipeCli.exe",NULL, NULL,NULL,TRUE,CREATE_DEFAULT_ERROR_MODE,/*0*/ NULL,NULL,&sui,&pi);//创建一个新的子进程,并将准备好的句柄信息传给子进程 CloseHandle(pi.hProcess); CloseHandle(pi.hThread); B、父进程中从管道读取代码如下: char buf[200]; DWORD dwRead; ReadFile(hRead,buf,200,&dwRead,NULL); MessageBox(buf); C、父进程中往管道写入代码如下: char buf[200]="专业的编程语言培训"; DWORD dwWrite; WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL); 子进程: 首先得到用于管道读取与写入用的句柄值(最好是放在视图的初始化更新函数里) hRead=GetStdHandle(STD_INPUT_HANDLE); hWrite=GetStdHandle(STD_OUTPUT_HANDLE); 读取部分代码: char buf[200]; DWORD dwRead; ReadFile(hRead,buf,200,&dwRead,NULL); MessageBox(buf); 写入部分代码: char buf[200]="http://www.it315.org"; DWORD dwWrite; WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL); --------------------------------------------(完) |
随便看 |
百科全书收录4421916条中文百科知识,基本涵盖了大多数领域的百科知识,是一部内容开放、自由的电子版百科全书。