天天看點

20、Windows API 程序間通信,郵槽(Mailslot)

    程序的位址空間是私有的。出于安全性的目的,如果一個程序不具有特殊的權限,是無法通路另外一個程序的記憶體空間的,也無法知道記憶體中儲存的資料的意義。但是在一些具體的應用情況下需要多個進行互相配合,有時計算機使用者也需要在多個應用程式之間交換資料。

Windows系統下,在程序間通信或共享資料的方式如下。

◇郵槽(Mailslot)。

    郵槽是最為簡單的程序間資料共享方式,一個程序建立并擁有一個郵槽,其他程序都可以打開這個郵槽并向其發送消息。

◇管道(Pipe)。

實質是一種共享的記憶體,由一個程序建立,其他程序連接配接,并可進行雙向的通信。

◇剪貼闆(Clipboard)。

    剪貼闆是重要的程序間資料共享方式,所有的程序都可以設定和修改剪貼闆,也都可以從剪貼闆擷取内容。

◇消息,具體是指WM_COPYDATA消息。

消息具有參數wParam和lParam。但是wParam和lParam最多是32位的。而WM_COPYDATA消息的參數不受wParam和lParam資料大小的限制,可以用于在程序間傳遞資料。

◇網絡。

    網絡可以在不同主機上的不同程式間通信,當然也可以在相同主機上的不同程式間通信。

◇FileMapping[2]

一、郵槽(MailSlot)

    使用郵槽通信的程序分為服務端和用戶端。郵槽由服務端建立,在建立時需要指定郵槽名,建立後服務端得到郵槽的句柄。在郵槽建立後,用戶端可以通過郵槽名打開郵槽,在獲得句柄後可以向郵槽寫入消息。

    郵槽通信是單向的,隻有服務端才能從郵槽中讀取消息,用戶端隻能寫入消息。消息是先入先出的。用戶端先寫入的消息在服務端先被讀取。

通過郵槽通信的資料可以是任意格式的,但是一條消息不能大于424位元組。郵槽除了在本機内進行程序間通信外,在主機間也可以通信。但是在主機間進行郵槽通信,資料通過網絡傳播時使用的是資料報協定(UDP),是以是一種不可靠的通信。通過網絡進行郵槽通信時,用戶端必須知道服務端的主機名或域名。

MailSlot的詳細介紹,可以參見[3],[4]也作了一些介紹。

郵槽通信服務端程式

20、Windows API 程式間通信,郵槽(Mailslot)
20、Windows API 程式間通信,郵槽(Mailslot)

通過mailslot程序間通信-服務端

通過mailslot程序間通信

**************************************/

/* 頭檔案 */

#include <windows.h>

#include <stdio.h>

/* 全局變量 */

HANDLE hSlot;

LPTSTR lpszSlotName = TEXT("\\\\.\\mailslot\\sample_mailslot");

LPTSTR Message = TEXT("Message for mailslot in primary domain.");

/* ************************************

* void main()

* 功能 程序間mailslot通信用戶端

void main()

{

DWORD cbMessage, cMessage, cbRead;

BOOL fResult;

LPTSTR lpszBuffer;

TCHAR achID[80];

DWORD cAllMessages;

HANDLE hEvent;

OVERLAPPED ov;

cbMessage = cMessage = cbRead = 0;

hSlot = CreateMailslot(

lpszSlotName, // mailslot 名

0, // 不限制消息大小

MAILSLOT_WAIT_FOREVER, // 無逾時

(LPSECURITY_ATTRIBUTES) NULL);

if (hSlot == INVALID_HANDLE_VALUE)

printf("CreateMailslot failed with %d\n", GetLastError());

return ;

}

else printf("Mailslot created successfully.\n");

while(1)

// 擷取mailslot資訊

fResult = GetMailslotInfo(hSlot, // mailslot 句柄

(LPDWORD) NULL, // 無最大消息限制

&cbMessage, // 下一條消息的大小

&cMessage, // 消息的數量

(LPDWORD) NULL); // 無時限

if (!fResult)

printf("GetMailslotInfo failed with %d.\n", GetLastError());

if (cbMessage == MAILSLOT_NO_MESSAGE)

// 沒有消息,過一段時間再去讀

Sleep(20000);

continue;

cAllMessages = cMessage;

while (cMessage != 0) // 擷取全部消息,有可能不隻一條

// 提示資訊

wsprintf((LPTSTR) achID,

"\nMessage #%d of %d\n",

cAllMessages - cMessage + 1,

cAllMessages);

// 配置設定空間

lpszBuffer = (LPTSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,

lstrlen((LPTSTR) achID)*sizeof(TCHAR) + cbMessage);

if( NULL == lpszBuffer )

// 讀取消息

fResult = ReadFile(hSlot, // mailslot句柄

lpszBuffer, // 緩存

cbMessage, // 消息的長度

&cbRead, // 實際讀取的長度

NULL);

printf("ReadFile failed with %d.\n", GetLastError());

GlobalFree((HGLOBAL) lpszBuffer);

// 處理資訊,顯示

lstrcat(lpszBuffer, (LPTSTR) achID);

printf("Contents of the mailslot: %s\n", lpszBuffer);

HeapFree(GetProcessHeap(),0,lpszBuffer);

// 計算剩餘的消息數

fResult = GetMailslotInfo(hSlot,

(LPDWORD) NULL,

&cbMessage,

&cMessage,

(LPDWORD) NULL);

printf("GetMailslotInfo failed (%d)\n", GetLastError());

郵槽通信用戶端程式

20、Windows API 程式間通信,郵槽(Mailslot)
20、Windows API 程式間通信,郵槽(Mailslot)

通過mailslot程序間通信-用戶端

LPTSTR lpszSlotName = TEXT("\\\\.\\mailslot\\sample_mailslot"); // mailslot名

LPTSTR lpszMessage = TEXT("Test Message for mailslot "); // 通信的内容

HANDLE hFile;

DWORD cbWritten;

DWORD cbMessage;

// 打開mailslot

hFile = CreateFile(lpszSlotName,

GENERIC_WRITE, // 可寫

FILE_SHARE_READ,

(LPSECURITY_ATTRIBUTES) NULL,

OPEN_EXISTING, // 打開一個已經存在的mailslot,應該由服務端已經建立

FILE_ATTRIBUTE_NORMAL,

(HANDLE) NULL);

if (hFile == INVALID_HANDLE_VALUE)

printf("CreateFile failed with %d.\n", GetLastError());

// 向mailslot寫入

fResult = WriteFile(hFile,

lpszMessage,

(DWORD) (lstrlen(lpszMessage)+1)*sizeof(TCHAR),

&cbWritten,

(LPOVERLAPPED) NULL);

printf("WriteFile failed with %d.\n", GetLastError());

// 結束

printf("Slot written to successfully.\n");

CloseHandle(hFile);

參考

[1] 精通Windows API 函數、接口、程式設計執行個體

繼續閱讀