Windows核心程式設計之郵槽實現程序間通訊
郵槽是Windows系統提供的一種單向通訊的機制。即程序中的一方只能寫入或讀取資料,而另一方則只能讀取或寫入資料。通過郵槽,使用者可以實現一對多或跨網路的程序之間的通訊。但是,郵槽能傳輸的資料非常小,一般在400KB左右。如果使用者操作的資料過大,可能會導致郵槽不能正常工作。
1.建立郵槽
使用者在實際程式設計時,可以使用Windows郵槽實現程序間通訊。但是使用者必須首先建立郵槽。在Windows系統中,使用者可以通過函式CreateMailslot函式建立郵槽。函式原型如下:
該函式的作用是建立郵槽並返回該郵槽的控制代碼。如果函式呼叫成功,將返回建立郵槽的控制代碼。否則,函式將返回INVALID_HANDLE_VALUE,表示郵槽建立失敗,引數說明如下:HANDLE CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize, DWORD lReadTimeout, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
引數lpName表示郵槽的名稱。郵槽名稱的格式為“\\.\mailslot\name”。其中,name表示郵槽的名稱。使用者在c++開發環境中,應該將其指定為“\\\\.\\mailslot\\name”。如果使用者在不同的主機上執行程式,則需要把名稱字串中的“.”換成對方主機名稱。
引數nMaxMessageSize 指定將通過郵槽傳送或接收的訊息的最大值,在實際程式設計中,一般將其設定為0,表示訊息的大小為任意值。
引數lReadTimeout表示程式讀取操作的超時時間。如果該引數值為0,則當郵槽中沒有任何訊息時,該函式將立即返回。如果該函式值為MAILSLOT_WAIT_FOREVER,則表示該函式將等待,直到郵槽中有訊息函式才返回。
引數lpSecurityAttributes是指向結構體LPSECURITY_ATTRIBUTES的指標,表示郵槽的安全屬性,一般情況下,將其設定為NULL,表示預設安全屬性。
一般情況下,函式CreateMailslot常被用於程序通訊的服務方,客戶端方使用CreateFile函式開啟指定的郵槽,再進行相關操作。
2.操作郵槽
使用者對郵槽進行操作包括將資料寫入郵槽和從郵槽中讀取資料等。在實際程式設計時,操作郵槽和操作檔案一樣,都是通過呼叫函式ReadFile()和WriteFile()進行讀寫操作。函式原型如下:
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
BOOL WriteFile(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);
3.郵槽例項
服務端:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE mail; //定義郵槽控制代碼
//建立郵槽
mail=CreateMailslot("\\\\.\\mailslot\\my",0,MAILSLOT_WAIT_FOREVER,NULL);
if(mail==INVALID_HANDLE_VALUE) //判斷郵槽控制代碼
{
cout<<"建立郵槽失敗!\r\n"; //提示資訊
return 0;
}
else
{
cout<<"建立郵槽成功,正在讀取資料……!\r\n";
char text[200]; //定義字元陣列
DWORD readtext; //獲取實際讀取值
while(1)
{
if(ReadFile(mail,text,200,&readtext,NULL)) //讀取資料
{
cout<<text<<endl; //顯示資料
}
}
}
Sleep(100000);
CloseHandle(mail);
return 0;
}
客戶端:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE mail2; //定義郵槽控制代碼
char text[]="您好,this is a message"; //初始化訊息
DWORD writetext; //獲取實際傳送值
mail2=CreateFile("\\\\.\\mailslot\\my",GENERIC_WRITE,FILE_SHARE_READ,
NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
//開啟檔案
if(INVALID_HANDLE_VALUE==mail2)
{
cout<<"郵槽開啟失敗!\r\n";
}
else
{
if(WriteFile(mail2,text,sizeof(text),&writetext,NULL)) //寫入資料
{
Sleep(1000);
cout<<"資料寫入成功\r\n"; //資料寫入成功
}
else
{
cout<<"資料寫入失敗\r\n";
}
CloseHandle(mail2); //關閉控制代碼
}
Sleep(10000);
return 0;
}