进程间的通信 不念不忘少年蓝@ 2022-08-06 06:22 218阅读 0赞 (一) 剪贴板 voidCClipBoardDlg::OnBnClickedBtnSend() \{ // TODO: 在此添加控件通知处理程序代码 if(!OpenClipboard()) \{ return; \} if (!EmptyClipboard()) \{ return; \} CString str; GetDlgItemText(IDC\_EDIT\_SEND, str); HANDLE hClip = GlobalAlloc(GMEM\_MOVEABLE, str.GetLength()+1); char \*pBuf = (char\*)GlobalLock(hClip); strcpy(pBuf, str); GlobalUnlock(hClip); SetClipboardData(CF\_TEXT, hClip); CloseClipboard(); \} voidCClipBoardDlg::OnBnClickedBtnRecv() \{ // TODO: 在此添加控件通知处理程序代码 if (!OpenClipboard()) \{ return; \} if (!IsClipboardFormatAvailable(CF\_TEXT)) \{ return; \} HANDLE hClip = GetClipboardData(CF\_TEXT); char \*pBuf = (char \*)GlobalLock(hClip); GlobalUnlock(hClip); SetDlgItemText(IDC\_EDIT\_RECV, pBuf); CloseClipboard(); \} (二) 匿名管道 本部分转自:[http://read.newbooks.com.cn/info/57058.html][http_read.newbooks.com.cn_info_57058.html] **概述** 管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。 **匿名管道实施细则** 匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句柄。CreatePipe()的函数原型为: voidCNamedPipeClientView::OnPipeConnect() \{ // TODO: 在此添加命令处理程序代码 if (!WaitNamedPipe(\_T(".//pipe//MyPipe"), NMPWAIT\_USE\_DEFAULT\_WAIT)) \{ AfxMessageBox(\_T("There is no named pipe instance currently")); return; \} hPipe = CreateFile(\_T(".//pipe//MyPipe"), GENERIC\_READ | GENERIC\_WRITE, 0, NULL, OPEN\_EXISTING,FILE\_ATTRIBUTE\_NORMAL, NULL); if (INVALID\_HANDLE\_VALUE == hPipe) \{ AfxMessageBox(\_T("Failed to pen the named pipe")); hPipe = NULL; return; \} \} voidCNamedPipeClientView::OnPipeRead() \{ // TODO: 在此添加命令处理程序代码 char buf\[100\]; DWORD dwRead; if(!ReadFile(hPipe, buf, 100, &dwRead, NULL)) \{ AfxMessageBox(\_T("Failed to read data from parent")); return; \} AfxMessageBox(buf); \} voidCNamedPipeClientView::OnPipeWrite() \{ // TODO: 在此添加命令处理程序代码 char buf\[\] = \{ \_T("命名管道测试程序")\}; DWORD dwWrite; if(!WriteFile(hPipe, buf, strlen(buf)+1, &dwWrite, NULL)) \{ AfxMessageBox(\_T("Failed to write data in parent")); return; \} \} (四) 邮槽 可实现跨网络一对多通信; 缺点是发送数据量在424字节以下; voidCMailSlotSrvView::OnMailslotRecv() \{ // TODO: 在此添加命令处理程序代码 HANDLE hMailslot = NULL; hMailslot = CreateMailslot(\_T(".//mailslot//MyMailSlot"), 0, MAILSLOT\_WAIT\_FOREVER,NULL); if (INVALID\_HANDLE\_VALUE == hMailslot) \{ AfxMessageBox(\_T("Failed to create the mailslot")); CloseHandle(hMailslot); hMailslot = NULL; return; \} char buf\[100\]; DWORD dwRead; if(!ReadFile(hMailslot, buf, 100, &dwRead, NULL)) \{ AfxMessageBox(\_T("Failed to receive data")); CloseHandle(hMailslot); return; \} AfxMessageBox(buf); CloseHandle(hMailslot); \} Client: voidCMailslotClieintView::OnMailslotSend() \{ // TODO: 在此添加命令处理程序代码 HANDLE hMailslot; hMailslot = CreateFile(\_T(".//mailslot//MyMailSlot"), GENERIC\_WRITE, FILE\_SHARE\_READ, NULL, OPEN\_EXISTING, FILE\_ATTRIBUTE\_NORMAL, NULL); if (INVALID\_HANDLE\_VALUE == hMailslot) \{ AfxMessageBox(\_T("Failed to open the mailslot")); return; \} char buf\[\] = \_T("邮槽测试程序"); DWORD dwWrite; if(!WriteFile(hMailslot, buf, strlen(buf)+1, &dwWrite, NULL)) \{ AfxMessageBox(\_T("Failed to write data")); CloseHandle(hMailslot); return; \} CloseHandle(hMailslot); \} voidCNamedPipeSrvView::OnPipeCreate() \{ // TODO: 在此添加命令处理程序代码 hPipe = CreateNamedPipe(\_T(".//pipe//MyPipe"), // dot stands local machine PIPE\_ACCESS\_DUPLEX | FILE\_FLAG\_OVERLAPPED, 0, 1, 1024, 1024, 0, NULL); if (INVALID\_HANDLE\_VALUE == hPipe) \{ AfxMessageBox(\_T("Failed to create named pipe")); hPipe = NULL; return; \} HANDLE hEvent; hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!hEvent) \{ AfxMessageBox(\_T("Failed to create event object")); return; \} OVERLAPPED overlap; ZeroMemory(&overlap, sizeof(OVERLAPPED)); overlap.hEvent = hEvent; if (!ConnectNamedPipe(hPipe, &overlap)) \{ if (ERROR\_IO\_PENDING != GetLastError()) \{ AfxMessageBox(\_T("Failed to wait to the client")); CloseHandle(hPipe); CloseHandle(hEvent); hPipe = NULL; return; \} \} if (WAIT\_FAILED == WaitForSingleObject(hEvent, INFINITE)) \{ AfxMessageBox(\_T("Failed to wait to the event object")); CloseHandle(hPipe); CloseHandle(hEvent); hPipe = NULL; return; \} CloseHandle(hEvent); \} voidCNamedPipeSrvView::OnPipeRead() \{ // TODO: 在此添加命令处理程序代码 char buf\[100\]; DWORD dwRead; if(!ReadFile(hPipe, buf, 100, &dwRead, NULL)) \{ AfxMessageBox(\_T("Failed to read data from parent")); return; \} AfxMessageBox(buf); \} voidCNamedPipeSrvView::OnPipeWrite() \{ // TODO: 在此添加命令处理程序代码 char buf\[\] = \{ \_T("http://www.baidu.com")\}; DWORD dwWrite; if(!WriteFile(hPipe, buf, strlen(buf)+1, &dwWrite, NULL)) \{ AfxMessageBox(\_T("Failed to write data in parent")); return; \} \} Client: <table style="width: 90%;"> <tbody> <tr> <td><span style="font-size: medium;">BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针<br> PHANDLE hWritePipe, // 指向写句柄的指针<br> LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性的指针<br> DWORD nSize // 管道大小<br>);</span></td> </tr> </tbody> </table> 通过hReadPipe和hWritePipe所指向的句柄可分别以只读、只写的方式去访问管道。在使用匿名管道通信时,服务器进程必须将其中的一个句柄传送给客户机进程。句柄的传递多通过继承来完成,服务器进程也允许这些句柄为子进程所继承。除此之外,进程也可以通过诸如DDE或共享内存等形式的进程间通信将句柄发送给与其不相关联的进程。 在调用CreatePipe()函数时,如果管道服务器将lpPipeAttributes 指向的SECURITY\_ATTRIBUTES数据结构的数据成员bInheritHandle设置为TRUE,那么CreatePipe()创建的管道读、写句柄将会被继承。管道服务器可调用DuplicateHandle()函数改变管道句柄的继承。管道服务器可以为一个可继承的管道句柄创建一个不可继承的副本或是为一个不可继承的管道句柄创建一个可继承的副本。CreateProcess()函数还可以使管道服务器有能力决定子进程对其可继承句柄是全部继承还是不继承。 在生成子进程之前,父进程首先调用Win32 API SetStdHandle()使子进程、父进程可共用标准输入、标准输出和标准错误句柄。当父进程向子进程发送数据时,用SetStdHandle()将管道的读句柄赋予标准输入句柄;在从子进程接收数据时,则用SetStdHandle()将管道的写句柄赋予标准输出(或标准错误)句柄。然后,父进程可以调用进程创建函数CreateProcess()生成子进程。如果父进程要发送数据到子进程,父进程可调用WriteFile()将数据写入到管道(传递管道写句柄给函数),子进程则调用GetStdHandle()取得管道的读句柄,将该句柄传入ReadFile()后从管道读取数据。 如果是父进程从子进程读取数据,那么由子进程调用GetStdHandle()取得管道的写入句柄,并调用WriteFile()将数据写入到管道。然后,父进程调用ReadFile()从管道读取出数据(传递管道读句柄给函数)。 在用WriteFile()函数向管道写入数据时,只有在向管道写完指定字节的数据后或是在有错误发生时函数才会返回。如管道缓冲已满而数据还没有写完,WriteFile()将要等到另一进程对管道中数据读取以释放出更多可用空间后才能够返回。管道服务器在调用CreatePipe()创建管道时以参数nSize对管道的缓冲大小作了设定。 匿名管道并不支持异步读、写操作,这也就意味着不能在匿名管道中使用ReadFileEx()和WriteFileEx(),而且ReadFile()和WriteFile()中的lpOverLapped参数也将被忽略。匿名管道将在读、写句柄都被关闭后退出,也可以在进程中调用CloseHandle()函数来关闭此句柄。 (三) 命名管道 命名管道可用网络间的通信,命名管道不需写身份验证代码,而socket则需要. Server: 命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节。我们在不了解网络协议的情况下,也可以利用命名管道来实现进程间的通信。 命名管道充分利用了Windows NT和Windows 2000内建的安全机制。 将命名管道作为一种网络编程方案时,它实际上建立了一个客户机/服务器通信体系,并在其中可靠地传输数据。 命名管道是围绕Windows文件系统设计的一种机制,采用“命名管道文件系统(Named Pipe File System,NPFS)”接口,因此,客户机和服务器可利用标准的Win32文件系统函数(例如:ReadFile和WriteFile)来进行数据的收发。 (by sunxin) MSDN: CreateNamedPipe Function Creates an instance of a named pipe and returns a handle for subsequent pipe operations. A named pipe server process uses this function either to create the first instance of a specific named pipe and establish its basic attributes or to create a new instance of an existing named pipe. Windows Me/98/95: Named pipes cannot be created. HANDLE WINAPI CreateNamedPipe( \_\_in LPCTSTR lpName, \_\_in DWORD dwOpenMode, \_\_in DWORD dwPipeMode, \_\_in DWORD nMaxInstances, \_\_in DWORD nOutBufferSize, \_\_in DWORD nInBufferSize, \_\_in DWORD nDefaultTimeOut, \_\_in LPSECURITY\_ATTRIBUTES lpSecurityAttributes ); [http_read.newbooks.com.cn_info_57058.html]: http://read.newbooks.com.cn/info/57058.html
相关 进程间通信 管道是Unix中最古老的进程间通信的形式。我们把从一个进程连接到另一个进程的一个数据流称为一个“管道“我们之前说进程间通信的本质是让不同的进程看到同一份资源,管道就是其中... 一时失言乱红尘/ 2024年04月25日 20:18/ 0 赞/ 131 阅读
相关 进程间通信 进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。 IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号 以你之姓@/ 2024年02月18日 20:08/ 0 赞/ 106 阅读
相关 进程间通信 进程间通信(IPC,Inter-Process Communication),是指两个或两个以上的进程之间传递数据或信号的一些技术或方法。进程是计算机系统分配资源的最小单位,每 ゞ 浴缸里的玫瑰/ 2023年01月02日 15:24/ 0 赞/ 210 阅读
相关 进程间的通信 (一) 剪贴板 voidCClipBoardDlg::OnBnClickedBtnSend() \{ // TODO: 在此添加控件通知处理程序代码 if(!Open 不念不忘少年蓝@/ 2022年08月06日 06:22/ 0 赞/ 219 阅读
相关 进程间通信 进程间通信的基本概念 进程间通信意味着两个不同进程间可以交换数据,操作系统中应提供两个进程可以同时访问的内存空间。 通过管道实现进程间通信 基于管道(P 港控/mmm°/ 2022年05月25日 09:42/ 0 赞/ 406 阅读
相关 进程间通信 程序员必须让拥有依赖关系的进程集协调,这样才能达到进程的共同目标。可以使用两种技术来达到协调。第一种技术在具有通信依赖关系的两个进程间传递信息。这种技术称做进程间通信(inte 谁践踏了优雅/ 2022年01月16日 14:09/ 0 赞/ 416 阅读
相关 进程间通信 转载自:[http://songlee24.github.io/2015/04/21/linux-IPC/][http_songlee24.github.io_2015_04_ 不念不忘少年蓝@/ 2021年09月23日 04:10/ 0 赞/ 555 阅读
相关 进程间通信 进程间通信 1. 前言 2. 使用文件实现进程间的通信 3. 使用管道实现进程间的通信 4. 共享内存 5. 以上三种通信方式的区别 青旅半醒/ 2021年08月30日 22:05/ 0 赞/ 567 阅读
还没有评论,来说两句吧...