郵槽

郵槽

郵槽Windows作業系統提供的一種單向進程間通信機制,可用於單機或者網路上的多機分散式環境。對於相對簡短的低頻率信息傳送,使用郵槽通常比命名管道或Unix域套接字更簡單。如低頻率的狀態改變訊息、作為對等點發現協定(peer-discovery protocol)的一部分。 郵槽機制允許短報文廣播給域上的計算機中所有監聽的進程。

基本介紹

  • 中文名:郵槽
  • 外文名:MailSlot
簡介,套用,實現,郵槽命名,郵槽報文內容,創建郵槽,寫入報文到郵槽,讀取郵槽報文,使用郵槽注意的問題,

簡介

郵槽採用的是一種比較簡單的客戶/伺服器體系。創建並擁有郵槽的進程為伺服器,不管該進程是在主域伺服器上還是在由Windows9X與NTWorkstation組成的工作站上都被視為郵槽伺服器。郵槽伺服器可以設定、修改郵槽的屬性,並讀取郵槽中的數據。而向指定的郵槽寫入訊息的進程則為郵槽客戶,同樣它不考慮郵槽所處機器在網路上的具體身份。郵槽客戶在獲得郵槽句柄之後,調用Writefile()函式將數據寫入郵槽,寫入郵槽的數據將加入到佇列中,也就是說郵槽客戶可以向伺服器傳送任何形式的數據,但伺服器不能向客戶傳送數據。郵槽工作方式有三大特點:
①單向通訊:創建郵槽的伺服器只能讀取訊息,不能寫入訊息,而客戶端則與之剛好相反。如果某一端應用程式要同時具備讀取與寫入的雙向功能,那么必須在兩端的應用程式分別建立兩個郵槽;②廣播訊息。假如在域上有若干計算機使用同樣的名稱創建郵槽,那么某一郵槽客戶可以一次性向所有的同名郵槽伺服器傳送訊息;③數據報傳輸。郵槽對訊息的傳輸為數據報方式,即客戶端只負責數據的傳送,而伺服器端並不回應客戶端傳送的數據是否接收到。
郵槽是一種伺服器-客戶接口。伺服器創建郵槽,客戶可以向命名的郵槽寫入內容。只有伺服器可以讀取郵槽,因此郵槽是一種單向進程間通信機制。郵槽不提供報文已收到的確認,因此是不可靠通信。
郵槽基於RPC協定,可以在同一個網路域上跨計算機使用。

套用

Windows信使服務是郵槽的最知名的套用。信使服務是一個郵槽伺服器,等待報文到達後,就彈窗顯示在螢幕上。
郵槽的套用舉例:
  • MAILSLOT\Messngr - 微軟NET SEND協定
  • MAILSLOT\Browse - 微軟網路鄰居共享資源瀏覽服務
  • MAILSLOT\Alerter
  • MAILSLOT\53cb31a0\UnimodemNotifyTSP
  • MAILSLOT\HydraLsServer - Microsoft Terminal Services Licensing
  • MAILSLOT\CheyenneDS -CABrightStor Discovery Service

實現

郵槽命名

郵槽的名字,從形式上看類似於檔案名稱。格式為“\\ComputerName\mailslot\[path]name”本地郵槽名字中的ComputerName使用.來代替,即“\\.\MailSlot\路徑\檔案名稱”。如果向當前傳送計算機所在工作組或域群發,可以使用“*”作為ComputerName。如果向指定工作組或域群發,應使用工作組或域名作為ComputerName。本機的Windows的信使服務使用的郵槽名字是”\\.\MailSlot\ messngr“。

郵槽報文內容

郵槽報文內容包含:接收日期、傳送人、接收人、具體內容。傳送人、接收人、具體內容三項內容之間使用位元組值0間隔。

創建郵槽

使用“CreateMailslot”創建郵槽。

寫入報文到郵槽

類似於寫入普通檔案,使用“CreateFile”打開郵槽,使用“WriteFile”將內容寫入。也可以使用“NetMessageBufferSend”直接傳送。

讀取郵槽報文

使用“GetMailSlotInfo”來判斷郵槽內是否有內容。發現有內容的時候,可以使用“ReadFile”讀取。如果“ReadFile”在使用MAILSLOT_WAIT_FOREVER標誌的郵槽上等待訊息到來,這時郵槽突然中止運行,那么這個套用會被永遠“掛起”直至重啟Windows系統。為此,讀郵槽的進程可以使用一個單獨執行緒執行讀掛起操作;主執行緒要結束進程時給一個全局標誌位置位,並給郵槽寫入一條訊息以喚醒讀郵槽執行緒。“SetMailslotInfo”設定讀取郵槽的逾時值。
例子:
//郵槽伺服器,負責創建郵槽,讀取郵槽#include <windows.h>#include <stdio.h>int main(){ HANDLE Mailslot; char buffer[256]; DWORD NumberOfBytesRead; //Create the mailslot Mailslot = CreateMailslot("////.//Mailslot//Myslot",  //指定郵槽的名字  0,                  //可寫入郵槽的訊息的最大位元組長度;為0表示接收任意長度訊息  MAILSLOT_WAIT_FOREVER, //等待或不等待,單位毫秒,MAILSLOT_WAIT_FOREVER無限期等待,0立即返回   NULL);               //訪問控制許可權,一般為NULL if (INVALID_HANDLE_VALUE == Mailslot) {  printf("Failed to create a mailslot %d/n", GetLastError());  return -1; } //Read data from the mailslot forever! while (0 != ReadFile(Mailslot, buffer, 256, &NumberOfBytesRead, NULL)) {  printf("%.*s/n",NumberOfBytesRead,buffer); } CloseHandle(Mailslot); return 0;}
//郵槽客戶端,用於傳送數據到郵槽伺服器#include <windows.h>#include <stdio.h>int main(int argc, char *argv[]){    HANDLE Mailslot;    DWORD BytesWritten;    CHAR ServerName[256];    //從命令行接受要傳送數據到的伺服器名    if (argc < 2)    {        printf("Usage: client <server name>/n");        return -1;    }    sprintf(ServerName, "////%s//Mailslot//Myslot",argv[1]);    Mailslot = CreateFile(ServerName, //郵槽名字        GENERIC_WRITE,      //必須為GENERIC_WRITE,因為客戶端只能向郵槽寫入數據        FILE_SHARE_READ,   /必須為FILE_SHARE_READ,因為郵槽伺服器需要做打開和讀操作        NULL,         OPEN_EXISTING,     //郵槽在本地且還沒有創建郵槽則當前調用失敗;郵槽在遠程,該參數無意義        FILE_ATTRIBUTE_NORMAL,        NULL);    if (INVALID_HANDLE_VALUE == Mailslot)    {        printf("WriteFile failed with error %d/n",GetLastError());        return -1;    }    if(0 == WriteFile(Mailslot, "This is a test", 14, &BytesWritten,NULL))    {        printf("WriteFile failed with error %d/n", GetLastError());        return -1;    }    printf("Wrote %d byteds/n", BytesWritten);    CloseHandle(Mailslot);    return 0;}

使用郵槽注意的問題

開發郵槽客戶機和伺服器套用時,所有Win32API函式(CreateFile和CreateMailslot除外)在調用失敗的情況下,都會返回0值。CreateFile和CreateMailslot這兩個API卻會返回INVALIDHANDLEVALUE(無效句柄值)。若這些API函式調用失敗,應用程式隨即應調用GetLastError函式,來接收與此次失敗有關的特殊信息。
對於Windows95和Windows98來說,值得注意的最後一個問題便是記憶體空間的“廢棄”,或者說記憶體空間產生了“漏洞”。在郵槽上使用逾時設定時,便有可能出現這一現象。假如用CreateMailslot函式創建一個郵槽,同時將逾時時間設為大於0的一個值,那么一旦超過這一時間,ReadFile函式便會造成記憶體空間的廢棄,生成所謂的“記憶體漏洞”。同時,函式會返回FALSE。經過多次ReadFile函式調用之後,系統就會變得極不穩定,以後逾時的ReadFile調用會開始返回TRUE。因此,系統不能再執行其他MS-DOS程式。為解決這個問題,請將逾時值設為0或者MAILSLOTWAITFOREVER。這樣便可禁止應用程式使用逾時機制,從而避免了實際產生的記憶體“漏洞”。

相關詞條

熱門詞條

聯絡我們