我們接着簡紹2種程序間通信的方法:
3.命名管道:
命名管道可以再2個任意程序間通信(包括網絡上的2個不同主機之上的程序) 他們建立了如客戶機/伺服器的連接配接
建立命名通道的機器為伺服器 連接配接命名通道的機器為客戶機
在命名管道的使用中 我們會使用事件對象來辨別管道的連接配接和讀寫操作
下面是要用到的函數:(有關詳細簡紹可以看msdn)
這個函數用來建立一個命名管道 失敗則傳回INVALID_HANDLE_VALUE 成功傳回管道句柄
HANDLE CreateNamedPipe(
LPCTSTR lpName, // pipe name
DWORD dwOpenMode, // pipe open mode
DWORD dwPipeMode, // pipe-specific modes//
DWORD nMaxInstances, // maximum number of instances
DWORD nOutBufferSize, // output buffer size
DWORD nInBufferSize, // input buffer size
DWORD nDefaultTimeOut, // time-out interval
LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD
);
這個函數用來等待客戶機的連接配接
BOOL ConnectNamedPipe(
HANDLE hNamedPipe, // handle to named pipe
LPOVERLAPPED lpOverlapped // overlapped structure
這個函數用來連接配接命名管道(客戶機使用)
BOOL WaitNamedPipe(
LPCTSTR lpNamedPipeName, // pipe name
DWORD nTimeOut // time-out interval
大緻流程如下:
建立命名管道(CreateNamedPipe)--------------->建立事件對象(CreateEvent)------->利用OVERLAPPED結構體關聯管道和事件對象------------------>調用
ConnectNamedPipe等待連接配接------->調用WaitForSingleObject函數等待事件對象發生
--------------------------------------------------------------代碼如下
HANDLE hPipe;
hPipe=CreateNamedPipe(".//pipe//Mypipe", //在程式中藥輸出/輸入'/'這要輸入'//' 一個代表轉義
PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,0,1,1024,1024,0,NULL);//建立命名管道
if (INVALID_HANDLE_VALUE==hPipe)
{
MessageBox("建立命名管道失敗!");
hPipe=NULL;
return;
}
HANDLE hEvent;
hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if (!hEvent)
MessageBox("建立事件對象失敗!");
CloseHandle(hPipe);
OVERLAPPED ovlap;
ZeroMemory(&ovlap,sizeof(OVERLAPPED));//把這個結構體中無關的資料成員全部清零
ovlap.hEvent=hEvent;
if (!ConnectNamedPipe(hPipe,&ovlap))
if (ERROR_IO_PENDING!=GetLastError())//我們采用的是重複模式
{ //在IO操作未完成的時候函數就傳回了 轉到背景執行 是以要判斷是否失敗要調用GetLastError()
MessageBox("等待客服端連接配接失敗!");
CloseHandle(hEvent);
CloseHandle(hPipe);
hEvent=NULL;
hPipe=NULL;
return;
}
/等待事件發生 當有事件發生時說明有用戶端連接配接到命名管道了
if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE)){
MessageBox("等待對象失敗!");
CloseHandle(hEvent);
hEvent=NULL;
CloseHandle(hEvent);
-----------------------------------------客戶機連接配接到命名管道
if(!WaitNamedPipe(".//pipe//Mypipe",NMPWAIT_USE_DEFAULT_WAIT)){
MessageBox("目前沒有可利用的命名管道執行個體!");
hPipe=CreateFile(".//pipe//Mypipe",
GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if ( INVALID_HANDLE_VALUE==hPipe)
MessageBox("打開命名管道失敗!");
--------------------------------------------讀檔案
char buf[100];
DWORD dwRead;//實際讀取資料數目
//讀取資料
if (!ReadFile(hPipe,buf,100,&dwRead,NULL))
MessageBox("讀取資料失敗!");
MessageBox(buf);
---------------------------------------------寫檔案
char buf[]="用戶端寫入資料";
DWORD dwWrite;//實際寫入的資料量
//寫入資料
if (!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
MessageBox("寫入資料失敗!");
4.油槽
也可以像命名管道一樣用于任意程序間通信 但要注意的是 油槽的建立者程序隻能從油槽中讀取資料 使用者程序隻能寫入資料
如果要實作雙向通信 隻需要建立2個油槽 油槽是基于廣播通信的 這樣我們可以用很少的代碼實作廣播 實作1對多的單向通信 才用socket編碼則較為複雜 缺點是發送資料量較
少 消息大小為424位元組以下
油槽建立比較簡單,下面是源代碼:
建立油槽 建立者進城 讀取資料
HANDLE hMailSlot;
hMailSlot=CreateMailslot(".//mailslot//MyMalislot",
0,MAILSLOT_WAIT_FOREVER,NULL);
if (INVALID_HANDLE_VALUE==hMailSlot)
MessageBox("油槽建立失敗!");
CloseHandle(hMailSlot);
if (!ReadFile(hMailSlot,buf,100,&dwRead,NULL))
CloseHandle(hMailSlot);
//使用者程序 寫入資料
HANDLE hMailslot;
hMailslot=CreateFile(".//mailslot//MyMalislot",GENERIC_WRITE,
FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hMailslot==INVALID_HANDLE_VALUE)
MessageBox("打開油槽失敗!");
char buf[]="油槽寫入資料";
if (!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL))
CloseHandle(hMailslot);
CreateFile WriteFile ReadFile可以用來建立,讀取檔案 也能用來建立,讀取油槽 命名管道等 見MSDN