最近在研究VXSIM和window程序之间的通讯,在PIPIE之下,发现其实是通过mailslot来实现通讯的,在找资料的过程中,发现相关资料不是很多,可以有用的为Johnny老兄的http://blog.csdn.net/johnny_83/archive/2007/10/12/1822220.aspx和http://www.csie.nctu.edu.tw/~jhhsu/main/IPC.htm,当然,我相信MSDN应该也有,无奈我这个嵌入软件开发为主的家伙,为了节省机器空间,没有在机器上装MSDN,以下是摘接的Johnny和部分相关自己的理解.
1: 进程间通讯方式有下列数种 :
Mailslot 與 Named Pipe 有些許的不同 . 首先 , Mailslot 是單向的 ( 也就是說 , 只能從 Mailslot Client 送 Message 至創造 Mailslot 的 Mailslot Server.)
其次 , 一個 Mailslot Client 可以將 Message 送往多個 Mailslot Server , 這種好處是可以對同一個 Domain 中的 Process 做廣播 . 但前題是 , 此 Message
的長度不可超過 425 bytes .此外 , 值得注意的是 : Mailslot 是使用 Datagram , 所以不能保證它是否可以送達遠端的 Process .
從 Mailslot Client 送往 Mailslot Server 的資料會暫時存在 Server 的 Mailslot 中 , 而且可以不斷的累積 , 不像 Named Pipe , 若 Named Pipe
Server 沒有讀取 Pipe 中的資料 , 則 Named Pipe Client 就再也寫不進去 .
Mailslot 所能容納的資料長度是有限制的 , 一般來說是 64k .
· 邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠的数据传输
1: 进程间通讯方式有下列数种 :
名稱 | 使用時機 |
Pipe | 將某一個 Process 的輸出當成是另一個 Process 的輸入時常用 Anonymous Pipe 來達成 . 而 Named Pipe 則是兩 Process 之間交換資料常用的方法 , 此兩個 Process 可以在同一部電腦上或不在同一部電腦上 . |
Mailslot | 某一個 Process 可以創造一 Mailslot , 而其它的 Process 就可以送資料至此 Mailslot . 送過來資料會一直被放在 Mailslot 中 , 直到被讀取為止 . Mailslot 也常用來對一個 Domain 中所有的 Process 做 Broadcast |
Memory Mapped File ( Shared Memory ) |
從系統取得一塊記憶體空間 , 然後兩個 Process 可將此記憶體空間分別映射到自己的定址空間中 , 並當成檔案 , 進而讀取或寫入資料 , 以達到交換資料的目的 . 特別要小心的是 , 用此種資料交換的方法必須謹慎處理同步的問題 . |
Socket | 兩個同時使用 Socket 的 Process 可互相傳遞資料 , 常用在異質的系統間 . |
RPC | |
DDE | |
COM |
Mailslot 與 Named Pipe 有些許的不同 . 首先 , Mailslot 是單向的 ( 也就是說 , 只能從 Mailslot Client 送 Message 至創造 Mailslot 的 Mailslot Server.)
其次 , 一個 Mailslot Client 可以將 Message 送往多個 Mailslot Server , 這種好處是可以對同一個 Domain 中的 Process 做廣播 . 但前題是 , 此 Message
的長度不可超過 425 bytes .此外 , 值得注意的是 : Mailslot 是使用 Datagram , 所以不能保證它是否可以送達遠端的 Process .
從 Mailslot Client 送往 Mailslot Server 的資料會暫時存在 Server 的 Mailslot 中 , 而且可以不斷的累積 , 不像 Named Pipe , 若 Named Pipe
Server 沒有讀取 Pipe 中的資料 , 則 Named Pipe Client 就再也寫不進去 .
Mailslot 所能容納的資料長度是有限制的 , 一般來說是 64k .
· 邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠的数据传输
· 邮槽是一种单向通信机制,创建邮槽的服务器进程读取 数据,打开邮槽的客户机进程写入数据
· 为保证邮槽在各种Windows平台下都能够正常工作,我们传输消息的时候,应将消息的长度限制在424字节以下
邮槽提供一种进程间通讯能力的方法。任何进程都可以创建一个邮槽,并成为一个邮槽服务器。其它调用邮槽的客户机进程能够通过邮槽名获得对这个邮槽的访问,并发送消息到邮槽服务器上。一个进程即可以当作邮槽服务器,也可以当作邮槽客户机,所以用多个邮槽来实现双向进程间通讯是可能的。
引入的信息经常被添加到邮槽中。邮槽保存这个消息直到创建进程有机会去读取它们。
除了为了有稍许简单化设计界面和附件在指定的网络域中为了在全部计算机中实现广播传送消息的能力之外,邮槽类似于命名管道。一个邮槽客户机能够发送消息到向一个本地计算机上的一个邮槽上,或者发送到其它计算机上的一个邮槽上,或者发送到在指定计算机区域中同名的全部邮槽上。广播到域上的消息不能够超过400个字节;被发送到一个单一的邮槽上的消息长度仅被限定在创建邮槽的人指定的最大消息长度。
关键点:邮槽为应用程序提供一种简易的发送和接受简短信息的方法。它们也提供了一种在指定网络区域中全部计算机间的广播式传播能力。
什么叫做邮槽?
邮槽是一种为了进程间通讯方法的机制。一个使用微软Windows写的应用程序能够在邮槽中存储消息(不尽然,我查找了一下,大部分系统都变相的支持他)。邮槽的拥有者能够重新找回被存储在邮槽中的消息。典型地,这些消息可以通过一个网络被发送到一个指定的计算机上或者在一个指定网络区域中的全部计算机上。这个域往往是一个工作站或者是一个共享一个组名的服务器。
邮槽的命名
当一个进程创建一个邮槽,这个邮槽的名称必须按照以下格式:\\.\mailslot\[path]name。一个邮槽名称需要这些元素:两个反斜杠去开始,一个句点,一个反斜杠跟在句点后,“mailslot”这个关键词和一个反斜杠,但是这些多试不重要的。一个邮槽名前可能加上一个被反斜杠分割的一个或多个伪仿的目录所组成的路径。例如:如果一个用户期望从Bob,Pete和Sue的Taxes消息,这个用户邮槽的应用程序可能允许这个用户去创建单独的邮槽为了各个发送者。
放入消息到一个邮槽中,一个进程需要打开一个已被命名的邮槽。在本地计算机上往邮槽中写信息,进程就必须要使用创建一个同名的邮槽。但是,这种情况很少。大部分情况下,一个进程用以下格式去写到一个指定的远程计算机上的邮槽上。
在一个给定域名的域中,向每个邮槽中放入消息时,采用以下格式:
在系统主要域中,往一个已有名字的每个邮槽中放入信息,进程可以采用以下格式:
Mailslot 名稱的格式有下列幾種 :
格式 | 說明 |
\\.\mailslot\[path]name | 將 Message 送至本機上的 mailslot |
\\ComputerName\mailslot\[path]name | 將 Message 送至指定電腦上的 mailslot |
\\DomainName\mailslot\[path]name | 廣播至某一個 domain 中所有的 mailslot |
\\*\mailslot\[path]name | 廣播至同一個 domain 中所有的 mailslot |
邮槽对象
通过CreateMailslot函数返回的句柄拥有GENERIC_READ,SYNCHRONIZE和 WRITE_DAC邮槽对象的访问权。
对于邮槽的GENERIC_READ访问权凝聚了STANDARD_RIGHTS_READ为了允许进程从邮槽中读数据,读邮槽的属性和读扩展属性。
邮槽函数
| |||||
| |||||
| |||||
额外的邮槽服务器使用函数:
1. DuplicateHandle;复制邮槽句柄。
2. ReadFile:从邮槽中返回消息。
3. GetFileTime:返回一个邮槽被创建的日期和时间。
4. SetFileTime:设置一个邮槽被创建的日期和时间。 |
例子(以下代码通过WIDOWS VC测试):
Mailslot Server 程式
#include <windows.h> #include <winbase.h> #include <stdio.h> #include <stdlib.h> #include <winuser.h> int main(void) { DWORD cbMessage, cMessage, cbRead; BOOL fResult; LPSTR lpszSlotName = "\\\\.\\mailslot\\sample_mailslot"; HANDLE hSlot1; LPSTR lpszBuffer; CHAR achID[80]; DWORD cAllMessages; BOOL Found=FALSE; hSlot1 = CreateMailslot(lpszSlotName, 0, MAILSLOT_WAIT_FOREVER, (LPSECURITY_ATTRIBUTES) NULL); if (hSlot1 == INVALID_HANDLE_VALUE) { printf("\nError CreateMailSlot"); return FALSE; } while(1) { Sleep(1); fResult = GetMailslotInfo(hSlot1, (LPDWORD) NULL, &cbMessage, &cMessage, (LPDWORD) NULL); if (!fResult) { printf("\nError GetMailslotInfo"); return FALSE; } printf("\n目前共有 %d 筆 Message 在 MailSlot 中",cMessage); if (cbMessage == MAILSLOT_NO_MESSAGE) continue; cAllMessages = cMessage; wsprintf((LPSTR) achID,"\n%d 筆中的第 %d 筆\n", cMessage, cAllMessages - cMessage + 1); // Allocate memory for the message. lpszBuffer = (LPSTR) GlobalAlloc(GPTR,lstrlen((LPSTR) achID) + cbMessage); lpszBuffer[0] = '\0'; fResult = ReadFile(hSlot1, lpszBuffer, cbMessage, &cbRead, (LPOVERLAPPED) NULL); if (!fResult) { printf("\nReadFile Error"); GlobalFree((HGLOBAL) lpszBuffer); return FALSE; } // Concatenate the message and the message-number string. lstrcat(lpszBuffer, (LPSTR) achID); // Display the message. printf("\n從 MailSlot 中取得的訊息為 %s",lpszBuffer); GlobalFree((HGLOBAL) lpszBuffer); } }
Mailslot Client 程式
#include <windows.h> #include <winbase.h> #include <stdio.h> #include <winuser.h> int main(int argc,char *argv[]) { BOOL fResult; LPSTR lpszSlotName = "\\\\.\\mailslot\\sample_mailslot"; char lpszMessage[100]; DWORD cbWritten; HANDLE hFile; DWORD Index=1; DWORD DelayTime=100; if(argc==2) DelayTime=atoi(argv[1]); hFile = CreateFile("\\\\.\\mailslot\\sample_mailslot", GENERIC_WRITE, FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("CreateFile Error!"); return FALSE; } while(1) { sprintf(lpszMessage,"Message : %d",Index++); fResult = WriteFile(hFile, lpszMessage, (DWORD) lstrlen(lpszMessage) + 1, &cbWritten, (LPOVERLAPPED) NULL); if (!fResult) { printf("WriteFile Error! %d",GetLastError()); return FALSE; } Sleep(DelayTime); printf("\n 送出訊息 : %d",Index); } }