VC深入详解之第十七章进程间的通信笔记

进程间的通信: 剪贴板 匿名管道 命名管道 邮遭 剪贴板: 打开剪贴板OpenClipBoard(),如果打开成功就返回非0值,否则返回0,如果某个程序已经打开了剪 贴板,则其他应用程序将不能修改剪贴板,直到前者调用了CloseClipboard函数。并且只有调用 EmptyClipboard函数之后,打开剪贴板的当前窗口才拥有剪贴板。SetClipboardData向剪贴板放置数据 。 void CClipboardDlg::OnBnClickedBtnSend() { if( OpenClipboard())//打开剪贴板 { CString str; HANDLE hClip; char *pBuf; EmptyClipboard();//清空剪贴板内容 GetDlgItemText(IDC_EDIT_SEND, str); hClip = GlobalAlloc( GMEM_MOVEABLE, str.GetLength() + 1);//分配全局内存 pBuf = (char *)GlobalLock( hClip);//对全局内存对象加锁 strcpy( pBuf, str); GlobalUnlock( hClip)//解锁; SetClipboardData( CF_TEXT, hClip); CloseClipboard(); } } void CClipboardDlg::OnBnClickedBtnRecv() { if( OpenClipboard()) { if( IsClipboardFormatAvailable( CF_TEXT))//判断是否期望的格式 { HANDLE hClip; char *pBUf; hClip = GetClipboardData( CF_TEXT ); pBUf = (char *)GlobalLock(hClip); GlobalUnlock( hClip); SetDlgItemText( IDC_EDIT_RECV, pBUf); } CloseClipboard(); } } 匿名管道: 匿名管道是一个未命名的、单项管道,通常用来在一个父进程之间传输数据。匿名管道只能实现本 地机器上两个进程间的通信,而不能实现跨网络通信 BOOL CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes,//不能为空,匿名管道只能在父进程和子进程之间进行通信 。子进程如果想要获取匿名管道只能从父进程继承而来。 DWORD nSize ); BOOL CreateProcess( LPCTSTR lpApplicationName,//应用程序路径和名称 LPTSTR lpCommandLine,//命令行参数 LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, //创建标志CREATE_NO_WINDOW LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo,//新进程主窗口如何显示 LPPROCESS_INFOMATION lpProcessInformation ); 实现步骤: 1.创建匿名管道 2.创建子进程 3.实现读取数据和写入数据函数 4.实现子进程 5.获得管道的读取和写入句柄 6.实现读写数据函数 总结:创建管道的时候会返回读句柄和写句柄,父继承通过调用ReadFile,并指定读句柄读取数据,通 过WriteFile,并指定写句柄写入数据。由于子进程继承自父进程,所以可以通过GetStdHandle (STD_INPUT_HANDLE)和GetStdHandle(STD_OUTPUT_HANDLE)获取句柄,获取的最佳时机是在窗口刚刚创建 完毕时,即OnInitialUpdate()虚函数中,然后通过ReadFile,WriteFile向管道读写数据。 void CParentView::OnPipeCreate() { SECURITY_ATTRIBUTES sa; sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; sa.nLength = sizeof(SECURITY_ATTRIBUTES); if(! CreatePipe(&hRead, &hWrite, &sa, 0)) { MessageBox("创建匿名管道失败!"); return; } STARTUPINFO sui; PROCESS_INFORMATION pi; ZeroMemory( &sui, sizeof(STARTUPINFO)); sui.cb = sizeof( STARTUPINFO); sui.dwFlags = STARTF_USESTDHANDLES; sui.hStdInput = hRead; sui.hStdOutput = hWrite; sui.hStdError = GetStdHandle(STARTF_USESTDHANDLES); if( !CreateProcess("..\\TEST\\Debug\\TEST.exe", NULL, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &sui, &pi)) { CloseHandle(hRead); CloseHandle(hWrite); hRead = NULL; hWrite = NULL; MessageBox("创建子进程失败!"); return; } else { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } } void CParentView::OnPipeRead() { char buf[100]; DWORD dwRead; if( !ReadFile(hRead, buf, 100, &dwRead, NULL)) { MessageBox("读取数据失败"); return ; } MessageBox(buf); } void CParentView::OnPipeWrite() { char buf[] = "bolg.csdn.com/lalor"; DWORD dwWrite; if( !WriteFile(hWrite, buf, strlen(buf) + 1, &dwWrite, NULL) ) { MessageBox("写入数据失败"); return; } } 命名管道: 命名管道不仅可以在本机上实现两个进程间的通信,还可以跨网络实现两个进程间的通信。 HANDLE CreateNamePipe( LPCTSTR lpName,"\\.\pipe\\pipename" DOWRD dwOpenMode,//指定访问模式,重叠方式等 DWORD dwPipeMode, DWORD nMaxInstances,//可创建的实例的最大数目 DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes ); 实现步骤: 1.创建命名管道 2.创建人工重置事件 3.等待连接 4.实现读取数据和写入数据函数 5.客户端连接管道 6.实现读取数据和写入数据函数 void CNamedPipeSrvView::OnPipeCreate() { SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = &sa; hPipe = CreateNamedPipe("\\\\.\\pipe\\MyPipe", PIPE_ACCESS_DUPLEX| FILE_FLAG_OVERLAPPED, 0, 1, 1024, 1024, 0, NULL); if( INVALID_HANDLE_VALUE == hPipe ) { MessageBox("创建命名管道失败"); hPipe = NULL; return; } HANDLE hEvent; hEvent = CreateEvent( NULL, TRUE, FALSE, NULL); if( !hEvent ) { MessageBox("创建事件对象失败!"); CloseHandle(hPipe); hPipe = NULL; return; } OVERLAPPED ovlap; ZeroMemory(&ovlap, sizeof(OVERLAPPED)); ovlap.hEvent = hEvent; if( !ConnectNamedPipe(hPipe, &ovlap)) { if(ERROR_IO_PENDING != GetLastError()) { MessageBox("等待客户端连接失败"); CloseHandle(hPipe); CloseHandle(hEvent); hPipe = NULL; return; } } if( WAIT_FAILED == WaitForSingleObject(hEvent, INFINITE)) { MessageBox("等待对象失败"); CloseHandle(hPipe); CloseHandle(hEvent); hPipe = NULL; return; } CloseHandle(hEvent); } void CNamedPipeSrvView::OnPipeRead() { char buf[100]; DWORD dwRead; if( !ReadFile(hPipe, buf, 100, &dwRead, NULL)) { MessageBox("读取数据失败"); return; } MessageBox(buf); } void CNamedPipeSrvView::OnPipeWrite() { char buf[] = "http://www.sunxin.org"; DWORD dwWrite; if( !WriteFile(hPipe, buf, strlen(buf) + 1 , &dwWrite, NULL)) { MessageBox("写入数据失败"); return; } } 客户端连接代码: void CNamedPipeCltView::OnPipeConnect() { if( !WaitNamedPipe("\\\\.\\pipe\\MyPipe", NMPWAIT_WAIT_FOREVER)) { MessageBox("当前没有可利用的命名管道"); return; } hPipe = CreateFile("\\\\.\\pipe\\MyPipe", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if ( INVALID_HANDLE_VALUE == hPipe ) { MessageBox("打开命名管道失败"); hPipe = NULL; return; } } 邮遭是基于广播通信体系设计出来的,它采用无连接的不可靠的数据传输。油槽是一种单向通信机 制,创建邮遭的服务器进程读取数据,打开油槽的客户机进程写入数据。 HANDLE CreateMailslot( LPCTSTR lpName, "\\.\mailsolt\[path]name" DWORD nMaxMessageSize,//可以写入邮遭单一消息的最大尺寸 DWORD lReadTimeout,//读取操作的超时时间 LPSECURITY_ATTRIBUTES lpSecurityAttributes ); 服务器端: void CMailSoltSrvView::OnMailslotRecv() { HANDLE hMailslot; hMailslot = CreateMailslot("\\\\.\\mailslot\\MyMailslot", 0, MAILSLOT_WAIT_FOREVER, NULL); if (INVALID_HANDLE_VALUE == hMailslot) { MessageBox("创建邮槽失败"); return; } char buf[100]; DWORD dwRead; if( !ReadFile(hMailslot, buf, 100, &dwRead, NULL)) { MessageBox("数据读取失败"); CloseHandle(hMailslot); return; } MessageBox(buf); CloseHandle(hMailslot); } 客户端: void CMailslotCltView::OnMailslotSend() { HANDLE hMailslot; hMailslot = CreateFile("\\\\.\\mailslot\\MyMailslot", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if( INVALID_HANDLE_VALUE == hMailslot ) { MessageBox("打开邮遭失败"); return; } char buf[] = "Hello, I'am lalor"; DWORD dwWrite; if ( ! WriteFile(hMailslot, buf, strlen(buf) + 1, &dwWrite, NULL)) { MessageBox("写入数据失败"); CloseHandle(hMailslot); return; } CloseHandle(hMailslot); }

你可能感兴趣的:(VC深入详解之第十七章进程间的通信笔记)