日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

Visual C++下对匿名管道的编程实现

發布時間:2025/3/20 c/c++ 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Visual C++下对匿名管道的编程实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

可以使用管道

Visual C++下對匿名管道的編程實現

概述

  管道(Pipe)實際是用于進程間通信的一段共享內存,創建管道的進程稱為管道服務器,連接到一個管道的進程為管道客戶機。一個進程在向管道寫入數據后,另一進程就可以從管道的另一端將其讀取出來。匿名管道(Anonymous Pipes)是在父進程和子進程間單向傳輸數據的一種未命名的管道,只能在本地計算機中使用,而不可用于網絡間的通信。

  匿名管道實施細則

  匿名管道由CreatePipe()函數創建,該函數在創建匿名管道的同時返回兩個句柄:管道讀句柄和管道寫句柄。CreatePipe()的函數原型為:

BOOL CreatePipe(PHANDLE hReadPipe, // 指向讀句柄的指針
 PHANDLE hWritePipe, // 指向寫句柄的指針
 LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全屬性的指針
 DWORD nSize // 管道大小
);

  通過hReadPipe和hWritePipe所指向的句柄可分別以只讀、只寫的方式去訪問管道。在使用匿名管道通信時,服務器進程必須將其中的一個句柄傳送給客戶機進程。句柄的傳遞多通過繼承來完成,服務器進程也允許這些句柄為子進程所繼承。除此之外,進程也可以通過諸如DDE或共享內存等形式的進程間通信將句柄發送給與其不相關聯的進程。

  在調用CreatePipe()函數時,如果管道服務器將lpPipeAttributes 指向的SECURITY_ATTRIBUTES數據結構的數據成員bInheritHandle設置為TRUE,那么CreatePipe()創建的管道讀、寫句柄將會被繼承。管道服務器可調用DuplicateHandle()函數改變管道句柄的繼承。管道服務器可以為一個可繼承的管道句柄創建一個不可繼承的副本或是為一個不可繼承的管道句柄創建一個可繼承的副本。CreateProcess()函數還可以使管道服務器有能力決定子進程對其可繼承句柄是全部繼承還是不繼承。

  在生成子進程之前,父進程首先調用Win32 API SetStdHandle()使子進程、父進程可共用標準輸入、標準輸出和標準錯誤句柄。當父進程向子進程發送數據時,用SetStdHandle()將管道的讀句柄賦予標準輸入句柄;在從子進程接收數據時,則用SetStdHandle()將管道的寫句柄賦予標準輸出(或標準錯誤)句柄。然后,父進程可以調用進程創建函數CreateProcess()生成子進程。如果父進程要發送數據到子進程,父進程可調用WriteFile()將數據寫入到管道(傳遞管道寫句柄給函數),子進程則調用GetStdHandle()取得管道的讀句柄,將該句柄傳入ReadFile()后從管道讀取數據。

  如果是父進程從子進程讀取數據,那么由子進程調用GetStdHandle()取得管道的寫入句柄,并調用WriteFile()將數據寫入到管道。然后,父進程調用ReadFile()從管道讀取出數據(傳遞管道讀句柄給函數)。

  在用WriteFile()函數向管道寫入數據時,只有在向管道寫完指定字節的數據后或是在有錯誤發生時函數才會返回。如管道緩沖已滿而數據還沒有寫完,WriteFile()將要等到另一進程對管道中數據讀取以釋放出更多可用空間后才能夠返回。管道服務器在調用CreatePipe()創建管道時以參數nSize對管道的緩沖大小作了設定。

  匿名管道并不支持異步讀、寫操作,這也就意味著不能在匿名管道中使用ReadFileEx()和WriteFileEx(),而且ReadFile()和WriteFile()中的lpOverLapped參數也將被忽略。匿名管道將在讀、寫句柄都被關閉后退出,也可以在進程中調用CloseHandle()函數來關閉此句柄。
總的來說,匿名管道程序是比較簡單的。在下面將要給出的程序示例中,將由父進程(管道服務器)創建一個子進程(管道客戶機),子進程回見個其全部的標準輸出發送到匿名管道中,父進程再從管道讀取數據,一直到子進程關閉管道的寫句柄。其中,匿名管道服務器程序的實現清單如下:

STARTUPINFO si;
PROCESS_INFORMATION pi;
char ReadBuf[100];
DWORD ReadNum;
HANDLE hRead; // 管道讀句柄
HANDLE hWrite; // 管道寫句柄
BOOL bRet = CreatePipe(&hRead, &hWrite, NULL, 0); // 創建匿名管道
if (bRet == TRUE)
 printf("成功創建匿名管道!/n");
else
 printf("創建匿名管道失敗,錯誤代碼:%d/n", GetLastError());
 // 得到本進程的當前標準輸出
 HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE);
 // 設置標準輸出到匿名管道
 SetStdHandle(STD_OUTPUT_HANDLE, hWrite);
 GetStartupInfo(&si); // 獲取本進程的STARTUPINFO結構信息
 bRet = CreateProcess(NULL, "Client.exe", NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi); // 創建子進程
 SetStdHandle(STD_OUTPUT_HANDLE, hTemp); // 恢復本進程的標準輸出
 if (bRet == TRUE) // 輸入信息
  printf("成功創建子進程!/n");
 else
  printf("創建子進程失敗,錯誤代碼:%d/n", GetLastError());
  CloseHandle(hWrite); // 關閉寫句柄
  // 讀管道直至管道關閉
  while (ReadFile(hRead, ReadBuf, 100, &ReadNum, NULL))
  {
   ReadBuf[ReadNum] = '/0';
   printf("從管道[%s]讀取%d字節數據/n", ReadBuf, ReadNum);
  }
  if (GetLastError() == ERROR_BROKEN_PIPE) // 輸出信息
   printf("管道被子進程關閉/n");
  else
   printf("讀數據錯誤,錯誤代碼:%d/n", GetLastError());

  在本示例中,將當前進程的標準輸出設置為使用匿名管道,再創建子進程,子進程將繼承父進程的標準輸出,然后再將父進程的標準輸出恢復為其初始狀態。于是父進程便可從管道讀取數據,直到有錯誤發生或關閉管道寫入端的所有句柄。創建的子進程只是向標準輸出和標準錯誤發送一些文本信息,其中發送給標準輸出的文本將重定向輸出到管道,發送給標準錯誤的文本將不改變輸出。下面給出子進程的實現代碼:

int main(int argc, char* argv[])
{
 for (int i = 0; i < 100; i++) // 發送一些數據到標準輸出和標準錯誤
 {
  printf("i = %d/n", i); // 打印提示
  cout << "標準輸出:" << i << endl; // 打印到標準輸出
  cerr << "標準錯誤:" << i << endl; // 打印到標準錯誤
 }
 return 0;
}

總結

以上是生活随笔為你收集整理的Visual C++下对匿名管道的编程实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。