[Win]进程间通信——邮槽Mailslot

来源:互联网 发布:淘宝商城电视机 编辑:程序博客网 时间:2024/06/06 09:16

进程间通信

进程的地址空间是私有的。出于安全性的目的,如果一个进程不具有特殊的权限,是无法访问另外一个进程的内存空间的,也无法知道内存中保存的数据的意义。但是在一些具体的应用情况下需要多个进行相互配合,有时计算机用户也需要在多个应用程序之间交换数据。
Windows系统下,在进程间通信或共享数据的方式如下。
  • 邮槽( Mailslot)。邮槽是最为简单的进程间数据共享方式,一个进程创建并拥有一个邮槽,其他进程都可以打开这个邮槽并向其发送消息。
  • 管道(Pipe)。实质是一种共享的内存,由一个进程创建,其他进程连接,并可进行双向的通信。
  • 剪贴板( Clipboard)。剪贴板是重要的进程间数据共享方式,所有的进程都可以设置和修改剪贴板,也都可以从剪贴板获取内容。
  • 消息,具体是指WM_COPYDATA消息。消息具有参数wParam和lParam。但是wParam和lParam最多是32位的。而WM_COPYDATA消息的参数不受wParam和lParam数据大小的限制,可以用于在进程间传递数据。
  • 网络。网络可以在不同主机上的不同程序间通信,当然也可以在相同主机上的不同程序间通信。
  • FileMapping. 

邮槽

使用邮槽通信的进程分为服务端和客户端。邮槽由服务端创建,在创建时需要指定邮槽名,创建后服务端得到邮槽的句柄。在邮槽创建后,客户端可以通过邮槽名打开邮槽,在获得句柄后可以向邮槽写入消息。
邮槽通信是单向的,只有服务端才能从邮槽中读取消息,客户端只能写入消息。消息是先入先出的。客户端先写入的消息在服务端先被读取。
通过邮槽通信的数据可以是任意格式的,但是一条消息不能大于424字节。
邮槽除了在本机内进行进程间通信外,在主机间也可以通信。但是在主机间进行邮槽通信,数据通过网络传播时使用的是数据报协议(UDP),所以是一种不可靠的通信。通过网络进行邮槽通信时,客户端必须知道服务端的主机名或域名。

实例

server:
[cpp] view plaincopy
  1. /*进程间mailslot通信服务器端 
  2. 创建了一个名为“\\\\.\\mailslot\\sample_mailslot”的邮槽,然后使用GetMailslotInfo函数读取消息数量。如果没有消息,则等待3s获取信息。循环直至有消息到达,然后一次性读出全部消息。*/  
  3. #include <windows.h>  
  4. #include <stdio.h>   
  5. HANDLE hSlot;  
  6. LPTSTR lpszSlotName = TEXT("\\\\.\\mailslot\\sample_mailslot");    
  7. void main()  
  8. {   
  9.     DWORD cbMessage, cMessage, cbRead,cAllMessages;   
  10.     BOOL bResult;    
  11.     TCHAR lpszBuffer[1000];   
  12.     TCHAR achID[80];    
  13.     cbMessage = cMessage = cbRead = 0;   
  14.     hSlot = CreateMailslot(  
  15.         lpszSlotName,       // mailslot 名  
  16.         0,                          // 不限制消息大小   
  17.         MAILSLOT_WAIT_FOREVER,         // 无超时   
  18.         NULL);   
  19.   
  20.     if (hSlot == INVALID_HANDLE_VALUE)   
  21.     {   
  22.         printf("CreateMailslot failed with %d\n", GetLastError());  
  23.         return ;   
  24.     }   
  25.     else   
  26.         printf("Mailslot created successfully.\n");   
  27.   
  28.     while(1)  
  29.     {  
  30.         // 获取mailslot信息  
  31.         bResult = GetMailslotInfo(hSlot, // mailslot 句柄   
  32.             (LPDWORD) NULL,               // 无最大消息限制  
  33.             &cbMessage,                   // 下一条消息的大小  
  34.             &cMessage,                    // 消息的数量  
  35.             (LPDWORD) NULL);           // 无时限  
  36.         if (!bResult)   
  37.         {   
  38.             printf("GetMailslotInfo failed with %d.\n", GetLastError());   
  39.             return ;   
  40.         }    
  41.         printf("MAILSLOT_NO_MESSAGE \n");  
  42.         if (cbMessage == MAILSLOT_NO_MESSAGE)   
  43.         {   
  44.             // 没有消息,过一段时间再去读  
  45.             Sleep(3000);  
  46.             continue;  
  47.         }    
  48.         printf("has MAILSLOT_NO_MESSAGE\n");  
  49.         cAllMessages = cMessage;   
  50.         while (cMessage != 0)  // 获取全部消息,有可能不只一条  
  51.         {   
  52.             // 提示信息  
  53.             wsprintf(achID, "\nMessage #%d of %d\n", cAllMessages - cMessage + 1, cAllMessages);               
  54.             // 读取消息   
  55.             if(!ReadFile(hSlot,lpszBuffer,cbMessage,&cbRead,NULL))  
  56.             {   
  57.                 printf("ReadFile failed with %d.\n", GetLastError());    
  58.                 return ;   
  59.             }    
  60.             lstrcat(lpszBuffer, achID); //连接  
  61.             printf("Contents of the mailslot: %s\n", lpszBuffer);//显示             
  62.             bResult = GetMailslotInfo(hSlot,NULL,&cbMessage,&cMessage,NULL); // 计算剩余的消息数,若cMessage=0,则退出子循环  
  63.             if (!bResult)   
  64.             {   
  65.                 printf("GetMailslotInfo failed (%d)\n", GetLastError());  
  66.                 return ;   
  67.             }   
  68.         }   
  69.     }   
  70. }  
client:
[cpp] view plaincopy
  1. /*进程间mailslot通信客户端 
  2. 客户端向邮槽发送消息需要首先打开邮槽,然后直接使用WriteFile函数写入。打开邮槽使用CreateFile函数。客户端在打开邮槽时需要知道邮槽名。*/  
  3. #include <windows.h>  
  4. #include <stdio.h>   
  5. LPTSTR lpszSlotName = TEXT("\\\\.\\mailslot\\sample_mailslot");     // mailslot名  
  6. LPTSTR lpszMessage = TEXT("Test Message for mailslot "); // 通信的内容  
  7. void main()  
  8. {     
  9.     DWORD cbWritten;   
  10.     DWORD cbMessage;  
  11.     // 打开mailslot  
  12.     HANDLE hFile = CreateFile(lpszSlotName,   
  13.         GENERIC_WRITE,      // 可写  
  14.         FILE_SHARE_READ,  
  15.         (LPSECURITY_ATTRIBUTES) NULL,   
  16.         OPEN_EXISTING,      // 打开一个已经存在的mailslot,应该由服务端已经创建  
  17.         FILE_ATTRIBUTE_NORMAL,   
  18.         (HANDLE) NULL);   
  19.     if (hFile == INVALID_HANDLE_VALUE)   
  20.     {   
  21.         printf("CreateFile failed with %d.\n", GetLastError());   
  22.         return ;   
  23.     }  
  24.     // 向mailslot写入  
  25.     int num=50;  
  26.     while(num)  
  27.     {  
  28.         Sleep(2000);  
  29.         num--;   
  30.         if(!WriteFile(hFile,   
  31.             lpszMessage,   
  32.             (DWORD) (lstrlen(lpszMessage)+1),    
  33.             &cbWritten,   
  34.             (LPOVERLAPPED) NULL))   
  35.         {   
  36.             printf("WriteFile failed with %d.\n", GetLastError());   
  37.             return ;   
  38.         }   
  39.         printf("Slot written to successfully.\n");   
  40.     }     
  41.     CloseHandle(hFile);  // 结束   
  42. }  
结果:
转载:http://blog.csdn.net/shimazhuge/article/details/9148507
0 0
原创粉丝点击