在Windows環境下,實現進程間通信的方式有很多種,如套接字、管道、遠程過程調用和NETBIOS等,郵槽是其中實現單通道進程間通信的一種。創建郵槽的進程被稱為郵槽服務器,而其它發送消息給郵槽的進程被稱為郵槽客戶端。郵槽客戶端能發送消息給本機的郵槽,也可發送消息給局域網內其他計算機內的郵槽,所有這些消息都存儲在郵槽內,直到郵槽服務器讀取它。這些消息通常是以廣播的方式發送,建立在面向無鏈接的數據報的基礎上,因此在線路不好時傳輸質量不可靠。
這種進程間通信的方式比較適用于在局域網環境內傳送和接收短消息,也可在局域網內向所有計算機廣播消息。
用郵槽進行進程間通信主要通過三個步驟來實現:創建郵槽服務器,向郵槽發送消息和從郵槽中讀取消息。下面筆者將用Windows的API函數來完成這三個步驟。
一、創建郵槽服務器
以下代碼用于創建一個名叫sample_mailslot的郵槽:
BOOL FAR PASCAL Makeslot( )
{
// 郵槽名稱都定義在\\.\mailslot\目錄下
LPSTR lpszSlotName = "\\\\.\\mailslot\\sample_mailslot";
// 郵槽句柄"hSlot1" 是一個全局變量
hSlot1 = CreateMailslot(lpszSlotName,0,
// 對接受的消息沒有最大值限制
MAILSLOT_WAIT_FOREVER, // 沒有最大讀延遲時間
(LPSECURITY_ATTRIBUTES) NULL); // 無安全屬性
if (hSlot1 == INVALID_HANDLE_VALUE)
//創建郵槽失敗
return FALSE;
return TRUE;
}
二、客戶端與郵槽服務器通信
客戶端通過API函數向郵槽發送消息,然后消息被廣播到域內的每一臺計算機上,但只有指定的郵槽接收這些消息。在這里要注意被廣播的消息每條不能超過400個字節,但對每個郵槽能接受的消息的數量沒有限制。
BOOL FAR PASCAL Writeslot( ) {
BOOL fResult;
HANDLE hFile;
DWORD cbWritten;
LPSTR lpszMessage = "Message for sample_mailslot in primary
domain";
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)
// 創建客戶端郵槽句柄失敗
return FALSE;
fResult = WriteFile(hFile, lpszMessage,
(DWORD) lstrlen(lpszMessage) + 1,
&&cbWritten,
(LPOVERLAPPED) NULL);
if (!fResult)
// 發送消息錯誤
return FALSE;
fResult = CloseHandle(hFile);
return TRUE;
}
三、從郵槽中讀取數據
郵槽服務器通過GetMailslotInfo函數判斷郵槽中是否有數據,如果有,則通過ReadFile函數從郵槽中讀取。下面的代碼完成從郵槽中讀取一條消息。
BOOL FAR PASCAL Readslot()
{
DWORD cbMessage, cMessage, cbRead;
BOOL fResult;
LPSTR lpszBuffer;
cbMessage = cMessage = cbRead = 0;
//郵槽句柄hSlot1是一個全局變量
fResult = GetMailslotInfo(hSlot1,
// 郵槽句柄
(LPDWORD) NULL, // 對消息的大小沒有最大限制
&&cbMessage, // 下一條消息的大小
&&cMessage, // 消息的數量 (LPDWORD) NULL); if(cbMessage ==
MAILSLOT_NO_MESSAGE)
// 郵槽內無消息
{ printf( "No waiting messages.");
return TRUE; }
// 為消息分配內存
lpszBuffer = (LPSTR) GlobalAlloc(GPTR, cbMessage);
lpszBuffer[0] = '\0'; fResult = ReadFile(hSlot1, lpszBuffer, cbMessage,
&&cbRead,
(LPOVERLAPPED) NULL);
// 顯示消息
Printf("%s",lpszBuffer);
GlobalFree((HGLOBAL) lpszBuffer);
return TRUE; }