天天看點

命名管道和油槽

我們接着簡紹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

上一篇: grr google