[概述]
簡單來說就是一個windows幫你建好、已經可以用的queue,可以塞資料進去然後依序再把它拿出來,也可以支援雙面塞入和取出(雙插頭?!)。它的好處在於可以同時一直拿資料也可以一直塞資料,所以通常可用在不同Thread做資料傳送使用。[架構]
主要分為Server端和Client端,下面實作是由Server端從Pipe收資料,Client端則是把資料塞到Pipe裡。我們Server端的步驟是:
1. 創建一個Name pipe
2. 跟Client做connect
3. 開始從Pipe讀資料出來
4. 收完資料以後要記得Disconnect和關Handle
Client端步驟則為:
1. 與伺服器作connect動作
2. 將Server端創好的Name pipe開起來(如開檔案)
3. 寫寫寫,寫東西到Pipe
4. 寫完收工關Handle
[實作]
Server端:
以\.\Pipe\Test當Name為例,m_hPipe是成員變數步驟1.
m_hPipe = CreateNamedPipe("\\\\.\\Pipe\\Test", PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, 1000, 1000, 1000, NULL); // 創建Named Pipe if (m_hPipe == INVALID_HANDLE_VALUE) ::AfxMessageBox(_T("Create Named Pipe fail."));
步驟2.
由於接下來要做的Connect步驟會一直等待Client端的連線,所以從這裡之後必須另外開一個Thread來執行此部分,所以另外創建一個ServerProc
if ( !ConnectNamedPipe(pView->m_hPipe, NULL)) // 等待Client Connect { CloseHandle(pView->m_hPipe); // 失敗要關閉Handle ::AfxMessageBox(_T("Connect Named Pipe fail.")); return false; }
步驟3.
Connect上以後就是開始做讀取的動作了,讀取動作跟讀檔案是完全一樣的,
阿要讀幾次就看個人,看你是要寫迴圈一直讀還是啥都可以,不過要記得跳離開就是了。
這裡範例就只讀一次這樣。
char strBuffer[1024] = {0}; DWORD ReadNum; if ( !ReadFile(pView->m_hPipe, strBuffer, sizeof(strBuffer), &ReadNum, NULL)) { CloseHandle(pView->m_hPipe); // 失敗要關閉Handle ::AfxMessageBox(_T("Read Pipe fail.")); } CString CStrTemp; CStrTemp = strBuffer; ::AfxMessageBox(CStrTemp);
步驟4.
打完收工要記得Disconnect和關閉Handle,不然會挫賽
if (DisconnectNamedPipe(pView->m_hPipe)) // 終止Server連線 { CloseHandle(pView->m_hPipe); // 關閉Pipe pView->m_hPipe = NULL; } else ::AfxMessageBox(_T("Disconnect Named Pipe fail")); return true;
Client端:
Client端的部分可以開個Thread去丟資料,總之不要跟Server是同Thread就是了,這樣才不會Block住。步驟1.
跟Server connect的方式是使用WaitNamedPipe
要注意的是,這個動作要比Server端的ConnectNamedPipe晚執行才可以,不然會錯亂。
if ( !WaitNamedPipe("\\\\.\\Pipe\\Test", NMPWAIT_WAIT_FOREVER)) // 等待Server連線 { ::AfxMessageBox(_T("Wait Pipe Fail.")); return false; }
步驟2.
使用CreateFile(開檔案的方式)來創建一個Handle供後來寫入Pipe使用
HANDLE hPipe = CreateFile("\\\\.\\Pipe\\Test", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hPipe == INVALID_HANDLE_VALUE) { ::AfxMessageBox(_T("Open Pipe Fail.")); return false; }
步驟3.
透過剛剛創建的Handle將資料寫入Pipe
寫入的方式也是使用寫檔的WriteFile來實現
CString CStrMessage = _T("Test message."); // 測試傳送的字串 DWORD WriteNum; if( !WriteFile(hPipe, CStrMessage , CStrMessage .GetLength(), &WriteNum, NULL)) { ::AfxMessageBox(_T("Write Message to Pipe Fail.")); return false; }
步驟4.
打完收工記得關Handle
CloseHandle(hPipe); // 關閉handle
就介紹到這裡囉~下回見
沒有留言:
張貼留言