四種線程間的通訊(筆記)

來源:互聯網
上載者:User
有四種方法
1.剪貼簿
  a.建立個ClipBoard的對話方塊應用程式
,加兩EditBox和兩個Button發送接收。
  b.具體代碼:
    發送端代碼:
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();
}
     接收端代碼:
if(OpenClipboard())
{
  if(IsClipboardFormatAvailable(CF_TEXT))
  {
   HANDLE hClip;
   char *pBuf;
   hClip=GetClipboardData(CF_TEXT);
   pBuf=(char*)GlobalLock(hClip);
   GlobalUnlock(hClip);
   SetDlgItemText(IDC_EDIT_RECV,pBuf);
   CloseClipboard();
  }
}
2.匿名管道:只能在父子進程之間進行通訊
  a.先建一個Parent的單文檔應用程式,增加“建立管道”“讀取資料”“寫入資料”三個菜單
  b.增加成員變數HANDLE類型的hRead,hWrite,初始設定變數,並在解構函式中釋放控制代碼
  c.響應菜單代碼:
void CParentView::OnPipeCreate() 菜單“建立管道”代碼
{
// TOD Add your command handler code here
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle=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);關閉控制代碼,將核心對象的使用計數減少1,這樣當作業系統發現核心對象的使用計數為0時,將清除核心對象。
  hRead=NULL;
  hWrite=NULL;
  MessageBox("建立子進程失敗!");
  return;
}
else
{
  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);
}
}void CParentView::OnPipeRead() 菜單“讀取資料”代碼
{
// TOD 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() 菜單“寫入資料”代碼
{
// TOD 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;
}
}
     d.再建一個Child的單文檔,在View中增加兩個成員hRead和hWrite.在OnInitialUpdate()中得到控制代碼的值。
void CChildView::OnInitialUpdate()
{
CView::OnInitialUpdate();

// TOD Add your specialized code here and/or call the base class
hRead=GetStdHandle(STD_INPUT_HANDLE);注意這句代碼!
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
}     e.加菜單“讀取資料”“寫入資料”其代碼如下:
void CChildView::OnPipeRead()
{
// TOD 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()
{
// TOD Add your command handler code here
char buf[]="匿名管道測試程式";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
  MessageBox("寫入資料失敗!");
  return;
}
}3.具名管道:還可以跨網路通訊,伺服器只能在win2000和NT下運行!而用戶端可以在95下運行。關鍵函數CreateNamedPipe
  a.先建一個NamedPipeSRV單文檔應用程式,加菜單“建立管道”“讀取資料”“寫入資料”
  b.在View中增加Handle變數hPipe,注意在解構函式中釋放它!
  c.響應菜單,建立具名管道
void CNamedPipeSrvView::OnPipeCreate()
{
// TOD Add your command handler code here
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);
  hPipe=NULL;
  return;
}
OVERLAPPED ovlap;
ZeroMemory(&ovlap,sizeof(OVERLAPPED));
ovlap.hEvent=hEvent;
if(!ConnectNamedPipe(hPipe,&ovlap))
{
  if(ERROR_IO_PENDING!=GetLastError())
  {
   MessageBox("等待用戶端串連失敗!");
   CloseHandle(hPipe);
   CloseHandle(hEvent);
   hPipe=NULL;
   return;
  }
}
if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE))
{
  MessageBox("等待對象失敗!");
  CloseHandle(hPipe);
  CloseHandle(hEvent);
  hPipe=NULL;
  return;
}
CloseHandle(hEvent);
}void CNamedPipeSrvView::OnPipeRead()
{
// TOD Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
  MessageBox("讀取資料失敗!");
  return;
}
MessageBox(buf);
}void CNamedPipeSrvView::OnPipeWrite()
{
// TOD Add your command handler code here
char buf[]="http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
  MessageBox("寫入資料失敗!");
  return;
}
}      d.再建一個NamedPipeCLT單文檔工程,加菜單“串連管道”“讀取資料”“寫入資料”,當然別忘記成員變數hPipe的定義和初始化
      e.響應菜單代碼
void CNamedPipeCltView::OnPipeConnect() 串連管道
{
// TOD Add your command handler code here
if(!WaitNamedPipe("//./pipe/MyPipe",NMPWAIT_WAIT_FOREVER))
{
  MessageBox("當前沒有可利用的具名管道執行個體!");
  return;
}
hPipe=CreateFile("//./pipe/MyPipe",GENERIC_READ | GENERIC_WRITE,
  0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hPipe)
{
  MessageBox("開啟具名管道失敗!");
  hPipe=NULL;
  return;
}
}void CNamedPipeCltView::OnPipeRead() 讀取資料
{
// TOD Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
  MessageBox("讀取資料失敗!");
  return;
}
MessageBox(buf);
}void CNamedPipeCltView::OnPipeWrite() 寫入資料
{
// TOD Add your command handler code here
char buf[]="具名管道測試程式";
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
  MessageBox("寫入資料失敗!");
  return;
}
}4.郵槽,使用時應將訊息長度限制在424位元組以下,關鍵函數CreateMailSlot()
  a.先建一個MailSlotSRV工程,加菜單“接收資料”
  b.訊息響應代碼:
void CMailslotSrvView::OnMailslotRecv() 菜單“接收資料”的代碼
{
// TOD Add your command handler code here
HANDLE hMailslot;
hMailslot=CreateMailslot("//./mailslot/MyMailslot",0,
  MAILSLOT_WAIT_FOREVER,NULL);
if(INVALID_HANDLE_VALUE==hMailslot)
{
  MessageBox("建立油槽失敗!");
  return;
}
char buf[100];
DWORD dwRead;
if(!ReadFile(hMailslot,buf,100,&dwRead,NULL))
{
  MessageBox("讀取資料失敗!");
  CloseHandle(hMailslot);
  return;
}
MessageBox(buf);
CloseHandle(hMailslot);
}
    c.加工程MailSlotCLT,加菜單“發送資料”
    d.加訊息響應,添加代碼,用戶端也比較簡單。
void CMailslotCltView::OnMailslotSend() 菜單“發送資料”的代碼
{
// TOD Add your command handler code here
HANDLE hMailslot;
hMailslot=CreateFile("//./mailslot/MyMailslot",GENERIC_WRITE,
  FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hMailslot)
{
  MessageBox("開啟油槽失敗!");
  return;
}
char buf[]="http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL))
{
  MessageBox("寫入資料失敗!");
  CloseHandle(hMailslot);
  return;
}
CloseHandle(hMailslot);
}5.以上4種方法各有優缺點:剪貼簿比較簡單。郵槽是基於廣播的,可以一對多發送。但只能一個發送,一個接收,要想同時發送接收,須寫兩次代碼。
具名管道和郵槽可以進行網路通訊。
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.