1. 程式人生 > >孫鑫vc++ 17 程序間通訊(3) 命名管道

孫鑫vc++ 17 程序間通訊(3) 命名管道

一、基礎知識

1.命名管道

(1)命名管道是圍繞Windows檔案系統設計的一種機制,採用“‘命名管道檔案系統’(Named Pipe File System,NPFS)“介面

(2)命名管道通過網路來完成程序間的通訊,它遮蔽了底層的網路協議細節;命名管道不僅可以在本機上實現兩個程序間的通訊,還可以跨網路實現兩個程序間的通訊

(3)命名管道分為客戶端和伺服器,兩者的區別在於:伺服器是唯一有權建立命名管道的程序,只有他才能接受管道客戶端的請求;同時,對同一個命名管道的例項來說,在某一時刻,他只能和一個客戶端進行通訊

(4)命名管道提供了兩種基本通訊模式:位元組模式和訊息模式;

(5)位元組模式:資料以一個連續的位元組流的形式在客戶機和伺服器之間流動

(6)訊息模式:客戶機和伺服器通過一系列不連續的資料單位,進行資料的收發,每次管道上發出了一個訊息後,他必須作為完整的資訊讀入

(7)在採用命名管道進行通訊的兩個程序之間,不需要有任何的關係,可以獨立的啟動這兩個程序

二、從程式碼進行分析

1.伺服器程序

//建立命名管道

void CNamedPipSrvView::OnCreatePipe()
{
 // TODO: Add your command handler code here

 hPipe = CreateNamedPipe(_T("\\\\.\\pipe\\MyPipe"),
  PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
  0,
  1,
  1024,
  1024,
  0,
  NULL);
 if (INVALID_HANDLE_VALUE == hPipe)
 {
  MessageBox(_T("管道建立失敗!"));
  hPipe = NULL;
  return;
 }

 HANDLE hEvent;

 hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

 OVERLAPPED ovlap;
 ZeroMemory(&ovlap,sizeof(ovlap));

 ovlap.hEvent = hEvent;

 if (!ConnectNamedPipe(hPipe,&ovlap))
 {
  if (ERROR_IO_PENDING != GetLastError())
  {
   MessageBox(_T("等待客戶連線失敗!"));
   CloseHandle(hEvent);
   CloseHandle(hPipe);
   hPipe = NULL;
   return;
  } 
 }
 if (WAIT_FAILED == WaitForSingleObject(hEvent,INFINITE))
 {
  MessageBox(_T("等待事件物件失敗!"));
  CloseHandle(hEvent);
  CloseHandle(hPipe);
  hPipe = NULL;
  return;
 }
 CloseHandle(hEvent);
 
}

 

//向管道寫入資料

void CNamedPipSrvView::OnWrite()
{
 // TODO: Add your command handler code here
 char buf[] = "伺服器程序寫入的資料";
 DWORD dwWrite;
 if (!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
 {
  ::MessageBox(m_hWnd,_T("寫入資料失敗!"),NULL,MB_OK);
  return;
 }
}

 

//從管道讀取資料

void CNamedPipSrvView::OnRead()
{
 // TODO: Add your command handler code here
 char buf[100];
 DWORD dwRead;
 if (!ReadFile(hPipe,buf,100,&dwRead,NULL))
 {
  ::MessageBox(m_hWnd,_T("讀取資料失敗!"),NULL,MB_OK);
  return;
 }
 ::MessageBox(m_hWnd,(LPCTSTR)buf,NULL,MB_OK);
}

2.客戶端程序

//連線管道

void CNamedPipCltView::OnOpen()
{
 // TODO: Add your command handler code here
 if (!WaitNamedPipe(_T("\\\\.\\pipe\\MyPipe"),NMPWAIT_WAIT_FOREVER))
 {
  MessageBox(_T("當前沒有可利用的命名管道!"));
  return;
 }

 hPipe = CreateFile(_T("\\\\.\\pipe\\MyPipe"),
  GENERIC_READ | GENERIC_WRITE,
  0,
  NULL,
  OPEN_EXISTING,
  FILE_ATTRIBUTE_NORMAL,
  NULL);

 if (INVALID_HANDLE_VALUE == hPipe)
 {
  MessageBox(_T("開啟命名管道失敗!"));
  hPipe = NULL;
  return;
 }
}

 

//向管道寫入資料

void CNamedPipCltView::OnWrite()
{
 // TODO: Add your command handler code here
 char buf[] = "客戶端程序寫入的資料";
 DWORD dwWrite;
 if (!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
 {
  ::MessageBox(m_hWnd,_T("寫入資料失敗!"),NULL,MB_OK);
  return;
 }
}

 

//從管道讀取資料

void CNamedPipCltView::OnRead()
{
 // TODO: Add your command handler code here
 char buf[100];
 DWORD dwRead;
 if (!ReadFile(hPipe,buf,100,&dwRead,NULL))
 {
  ::MessageBox(m_hWnd,_T("讀取資料失敗!"),NULL,MB_OK);
  return;
 }
 ::MessageBox(m_hWnd,(LPCTSTR)buf,NULL,MB_OK);
}

3.需要掌握的函式

(1)CreateNamedPipe

(2)CreateEvent

(3)GetLastError

(4)ConnectNamedPipe

(5)WaitForSingleObject

(6)CreateFile