程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 詳細講解進程間通訊的四種方式

詳細講解進程間通訊的四種方式

編輯:C++入門知識

進程間通訊的四種方式:剪貼板、匿名管道、命名管道和郵槽

第一種:剪貼板
(1)新建一個基於對話框的應用程序,並設置好如下界面:

\

(2)分別編輯發送按鈕和接收按鈕的代碼:
[cpp] ?void CClipboardDlg::OnBtnSend()  

    // TODO: Add your control notification handler code here  
    if(OpenClipboard()) 
    { 
        CString str; 
        HANDLE hClip; 
        char *pBuf; 
        EmptyClipboard();//將剪貼板擁有權設置為當前窗口  
        GetDlgItemText(IDC_EDIT_SEND,str); 
        hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);//多分配一個字節,用於放置回車  
        pBuf=(char *)GlobalLock(hClip);//對一個內存對象加鎖並返回內存對象句柄  
        strcpy(pBuf,str); 
        GlobalUnlock(hClip);//解鎖  
        SetClipboardData(CF_TEXT,hClip);//放置數據  
        CloseClipboard();//關閉剪貼板  
    } 

 
void CClipboardDlg::OnBtnRecv()  

    // TODO: Add your control notification handler code here  
    if(OpenClipboard()) 
    { 
        //The IsClipboardFormatAvailable function determines whether the clipboard contains data in the specified format  
        if(IsClipboardFormatAvailable(CF_TEXT)) 
        { 
            HANDLE hClip; 
            char *pBuf; 
            hClip=GetClipboardData(CF_TEXT); 
            pBuf=(char *)GlobalLock(hClip);//The GlobalLock function locks a global memory object and returns a pointer to the first byte of the object's memory block  
            GlobalUnlock(hClip); 
            SetDlgItemText(IDC_EDIT_RECV,pBuf); 
            CloseClipboard(); 
        } 
    } 

void CClipboardDlg::OnBtnSend()
{
 // TODO: Add your control notification handler code here
 if(OpenClipboard())
 {
  CString str;
  HANDLE hClip;
  char *pBuf;
  EmptyClipboard();//將剪貼板擁有權設置為當前窗口
        GetDlgItemText(IDC_EDIT_SEND,str);
  hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);//多分配一個字節,用於放置回車
        pBuf=(char *)GlobalLock(hClip);//對一個內存對象加鎖並返回內存對象句柄
        strcpy(pBuf,str);
  GlobalUnlock(hClip);//解鎖
  SetClipboardData(CF_TEXT,hClip);//放置數據
  CloseClipboard();//關閉剪貼板
 }
}

void CClipboardDlg::OnBtnRecv()
{
 // TODO: Add your control notification handler code here
 if(OpenClipboard())
 {
  //The IsClipboardFormatAvailable function determines whether the clipboard contains data in the specified format
  if(IsClipboardFormatAvailable(CF_TEXT))
  {
            HANDLE hClip;
   char *pBuf;
      hClip=GetClipboardData(CF_TEXT);
   pBuf=(char *)GlobalLock(hClip);//The GlobalLock function locks a global memory object and returns a pointer to the first byte of the object's memory block
   GlobalUnlock(hClip);
   SetDlgItemText(IDC_EDIT_RECV,pBuf);
   CloseClipboard();
  }
 }
}


第二種:匿名管道
<1>新建一個基於單文檔的工程,工程名為"Parent"
(1)添加如下菜單項,並添加命令響應函數 CChildView::OnPipeRead()、CChildView::OnPipeWrite();

\

(2)在CParentView類中添加兩個句柄HANDLE hRead 和 HANDLE hWrite,屬性設為私有,並在構造函數中進行初始化,在析構函數中釋放該句柄
[cpp]
CParentView::CParentView() 

    // TODO: add construction code here  
    hRead=NULL; 
    hWrite=NULL; 

 
CParentView::~CChildView() 

    if(hRead) 
       CloseHandle(hRead); 
    if(hWrite) 
       CloseHandle(hWrite); 

CParentView::CParentView()
{
 // TODO: add construction code here
    hRead=NULL;
    hWrite=NULL;
}

CParentView::~CChildView()
{
 if(hRead)
    CloseHandle(hRead);
 if(hWrite)
    CloseHandle(hWrite);
}

(3)編寫CParentView::OnPipeCreate() 函數,注意用到兩個函數CreatePipe(...)和CreateProcess(...)分別用於創建管道和啟動子進程。代碼如下:
[cpp]
void CParentView::OnPipeCreate()  

    // TODO: Add your command handler code here  
    SECURITY_ATTRIBUTES sa;//定義一個安全屬性結構圖  
    sa.bInheritHandle=TRUE;//TRUE表示可以被子進程繼承  
    sa.lpSecurityDescriptor=NULL; 
    sa.nLength=sizeof(SECURITY_ATTRIBUTES); 
    if(CreatePipe(&hRead,&hWrite,&sa,0))//創建匿名管道  
    { 
        MessageBox("匿名管道創建失敗!"); 
        return ; 
    } 
   //如果創建成功則啟動子進程,將匿名管道的讀寫句柄傳遞給子進程  
   STARTUPINFO sui; 
   PROCESS_INFORMATION pi; 
   ZeroMemory(&sui,sizeof(STARTUPINFO));//將這個結構體內的所有成員設為0  
   sui.cb=sizeof(STARTUPINFO); 
   sui.dwFlags=STARTF_USESTDHANDLES; 
   sui.hStdInput=hRead; 
   sui.hStdOutput=hWrite; 
   sui.hStdError=GetStdHandle(STD_ERROR_HANDLE); 
   if(!CreateProcess("..\\Child\\Debug\\Child.exe",NULL,NULL,NULL, 
             TRUE,0,NULL,NULL,&sui,&pi)) 
   { 
       CloseHandle(hRead); 
       CloseHandle(hWrite); 
       hRead=NULL; 
       hWrite=NULL; 
       MessageBox("創建子進程失敗!"); 
       return; 
 
   } 
   else 
   { 
       CloseHandle(pi.hProcess);//關閉主進程句柄  
       CloseHandle(pi.hThread);//關閉主進程線程句柄   
   } 
    

void CParentView::OnPipeCreate()
{
 // TODO: Add your command handler code here
 SECURITY_ATTRIBUTES sa;//定義一個安全屬性結構圖
 sa.bInheritHandle=TRUE;//TRUE表示可以被子進程繼承
 sa.lpSecurityDescriptor=NULL;
 sa.nLength=sizeof(SECURITY_ATTRIBUTES);
 if(CreatePipe(&hRead,&hWrite,&sa,0))//創建匿名管道
 {
        MessageBox("匿名管道創建失敗!");
  return ;
 }
   //如果創建成功則啟動子進程,將匿名管道的讀寫句柄傳遞給子進程
   STARTUPINFO sui;
   PROCESS_INFORMATION pi;
   ZeroMemory(&sui,sizeof(STARTUPINFO));//將這個結構體內的所有成員設為0
   sui.cb=sizeof(STARTUPINFO);
   sui.dwFlags=STARTF_USESTDHANDLES;
   sui.hStdInput=hRead;
   sui.hStdOutput=hWrite;
   sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);
   if(!CreateProcess("..\\Child\\Debug\\Child.exe",NULL,NULL,NULL,
          TRUE,0,NULL,NULL,&sui,&pi))
   {
    CloseHandle(hRead);
    CloseHandle(hWrite);
    hRead=NULL;
    hWrite=NULL;
    MessageBox("創建子進程失敗!");
    return;

   }
   else
   {
    CloseHandle(pi.hProcess);//關閉主進程句柄
    CloseHandle(pi.hThread);//關閉主進程線程句柄
   }
  
}(4)編寫OnPipeRead()和OnPipeWrite()的具體實現:
[cpp]
void CParentView::OnPipeRead()  

    // TODO: Add your command handler code here  
    char buf[100]; 
    DWORD dwRead; 
    if(!ReadFile(hRead,buf,100,&dwRead,NULL)) 
    { 
        MessageBox("讀取數據失敗!"); 
        return; 
    } 
    MessageBox(buf); 

 
void CParentView::OnPipeWrite()  

    // TODO: Add your command handler code here  
    char buf[]="http://www.sunxin.org"; 
    DWORD dwWrite; 
    if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL)) 
    { 
        MessageBox("寫入數據失敗!"); 
        return; 
    } 

void CParentView::OnPipeRead()
{
 // TODO: Add your command handler code here
 char buf[100];
 DWORD dwRead;
 if(!ReadFile(hRead,buf,100,&dwRead,NULL))
 {
  MessageBox("讀取數據失敗!");
  return;
 }
 MessageBox(buf);
}

void CParentView::OnPipeWrite()
{
 // TODO: Add your command handler code here
 char buf[]="http://www.sunxin.org";
 DWORD dwWrite;
 if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
 {
  MessageBox("寫入數據失敗!");
  return;
 }
}

 

 

<2>在該工程中再添加一個項目,同樣是基於單文檔的,項目名為"Child",於"Parent"保持平級即可。
(1)添加如下菜單項,並添加命令響應函數 CChildView::OnPipeRead()、CChildView::OnPipeWrite();


(2)首先我們要獲得子進程的標准輸入和標准輸出句柄,這個可以在CChildView類的窗口完全創建的時候去獲取,此時我們可以用一個CChildView::OnInitialUpdate()的虛函數去獲取,OnInitialUpdate()是在窗口完全創建之後第一個執行的函數。
(3)在CChildView類中添加兩個句柄 HANDLE hRead 和 HANDLE hWrite,屬性設為私有,並在構造函數中進行初始化,在析構函數中釋放該句柄
[cpp]
CChildView::CChildView() 

    // TODO: add construction code here  
    hRead=NULL; 
    hWrite=NULL; 

 
CChildView::~CChildView() 

    if(hRead) 
       CloseHandle(hRead); 
    if(hWrite) 
       CloseHandle(hWrite); 

CChildView::CChildView()
{
 // TODO: add construction code here
    hRead=NULL;
    hWrite=NULL;
}

CChildView::~CChildView()
{
 if(hRead)
    CloseHandle(hRead);
 if(hWrite)
    CloseHandle(hWrite);
}(4)在OnInitialUpdate()函數中通過 GetStdHandle(STD_INPUT_HANDLE)、GetStdHandle(STD_OUTPUT_HANDLE)得到標准輸入輸出句柄
[cpp]
hRead=GetStdHandle(STD_INPUT_HANDLE);//得到管道的讀取句柄  
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);//得到管道的寫入句柄 

 hRead=GetStdHandle(STD_INPUT_HANDLE);//得到管道的讀取句柄
 hWrite=GetStdHandle(STD_OUTPUT_HANDLE);//得到管道的寫入句柄(5)接著編寫讀取進程OnPipeRead()和寫入進程OnPipeWrite()代碼的具體實現:
[cpp]
void CChildView::OnPipeRead()  

    // TODO: Add your command handler code here  
    char buf[100]; 
    DWORD dwRead; 
    if(!ReadFile(hRead,buf,100,&dwRead,NULL)) 
    { 
        MessageBox("讀取數據失敗!"); 
        return; 
    } 
    MessageBox(buf); 

 
void CChildView::OnPipeWrite()  

    // TODO: Add your command handler code here  
    char buf[]="匿名管道測試程序"; 
    DWORD dwWrite; 
    if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL)) 
    { 
        MessageBox("寫入數據失敗!"); 
        return; 
    } 

void CChil\
dView::OnPipeRead()
{
 // TODO: Add your command handler code here
 char buf[100];
 DWORD dwRead;
 if(!ReadFile(hRead,buf,100,&dwRead,NULL))
 {
  MessageBox("讀取數據失敗!");
  return;
 }
 MessageBox(buf);
}

void CChildView::OnPipeWrite()
{
 // TODO: Add your command handler code here
 char buf[]="匿名管道測試程序";
 DWORD dwWrite;
 if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
 {
  MessageBox("寫入數據失敗!");
  return;
 }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved