複製鏈接
請複製以下鏈接發送給好友

郵槽

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

郵槽簡介

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

郵槽應用

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。這樣便可禁止應用程序使用超時機制,從而避免了實際產生的內存“漏洞”。
參考資料