我是靠谱客的博主 英勇西装,最近开发中收集的这篇文章主要介绍基于visual c++之windows核心编程代码分析(17)通过pipe进程间通信,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

管道是一种用于在进程间共享数据的机制,其实质是一段共享内存。Windows系统为这段共享的内存设计采用数据流I/0的方式来访问。由一个进程读、另一个进程写,类似于一个管道两端,因此这种进程间的通信方式称作“管道”。

    管道分为匿名管道和命名管道。

    匿名管道只能在父子进程间进行通信,不能在网络间通信,而且数据传输是单向的,只能一端写,另一端读。

    命令管道可以在任意进程间通信,通信是双向的,任意一端都可读可写,但是在同一时间只能有一端读、一端写。

 

管道客户端代码实现如下

[cpp]  view plain  copy
  1. /* 头文件 */  
  2. #include <windows.h>   
  3. #include <stdio.h>  
  4. #include <conio.h>  
  5. #include <tchar.h>  
  6. /* 常量 */  
  7. #define BUFSIZE 512  
  8. /* ************************************ 
  9. * int main(VOID)  
  10. * 功能    pipe 通信服务端主函数 
  11. **************************************/  
  12. int main(int argc, TCHAR *argv[])   
  13. {   
  14.     HANDLE hPipe;   
  15.     LPTSTR lpvMessage=TEXT("Default message from client");   
  16.     TCHAR chBuf[BUFSIZE];   
  17.     BOOL fSuccess;   
  18.     DWORD cbRead, cbWritten, dwMode;   
  19.     LPTSTR lpszPipename = TEXT("\\.\pipe\samplenamedpipe");   
  20.   
  21.     if( argc > 1 )   // 如果输入了参数,则使用输入的参数  
  22.         lpvMessage = argv[1];  
  23.     while (1)   
  24.     {   
  25.         // 打开一个命名pipe  
  26.         hPipe = CreateFile(   
  27.             lpszPipename,   // pipe 名   
  28.             GENERIC_READ |   GENERIC_WRITE,     //  可读可写  
  29.             0,              // 不共享  
  30.             NULL,           // 默认安全属性  
  31.             OPEN_EXISTING,  // 已经存在(由服务端创建)  
  32.             0,              // 默认属性  
  33.             NULL);      
  34.         if (hPipe != INVALID_HANDLE_VALUE)   
  35.             break;   
  36.   
  37.         // 如果不是 ERROR_PIPE_BUSY 错误,直接退出    
  38.         if (GetLastError() != ERROR_PIPE_BUSY)   
  39.         {  
  40.             printf("Could not open pipe");   
  41.             return 0;  
  42.         }  
  43.   
  44.         // 如果所有pipe实例都处于繁忙状态,等待2秒。  
  45.         if (!WaitNamedPipe(lpszPipename, 2000))   
  46.         {   
  47.             printf("Could not open pipe");   
  48.             return 0;  
  49.         }   
  50.     }   
  51.   
  52.     // pipe已经连接,设置为消息读状态   
  53.     dwMode = PIPE_READMODE_MESSAGE;   
  54.     fSuccess = SetNamedPipeHandleState(   
  55.         hPipe,    // 句柄  
  56.         &dwMode,  // 新状态  
  57.         NULL,     // 不设置最大缓存  
  58.         NULL);    // 不设置最长时间  
  59.     if (!fSuccess)   
  60.     {  
  61.         printf("SetNamedPipeHandleState failed");   
  62.         return 0;  
  63.     }  
  64.   
  65.     // 写入pipe  
  66.     fSuccess = WriteFile(   
  67.         hPipe,                  // 句柄  
  68.         lpvMessage,             // 写入的内容  
  69.         (lstrlen(lpvMessage)+1)*sizeof(TCHAR), // 写入内容的长度  
  70.         &cbWritten,             // 实际写的内容  
  71.         NULL);                  // 非 overlapped   
  72.     if (!fSuccess)   
  73.     {  
  74.         printf("WriteFile failed");   
  75.         return 0;  
  76.     }  
  77.   
  78.     do   
  79.     {   
  80.         // 读回复   
  81.         fSuccess = ReadFile(   
  82.             hPipe,    // 句柄  
  83.             chBuf,    // 读取内容的缓存  
  84.             BUFSIZE*sizeof(TCHAR),  // 缓存大小  
  85.             &cbRead,  // 实际读的字节  
  86.             NULL);    // 非 overlapped   
  87.   
  88.         if (! fSuccess && GetLastError() != ERROR_MORE_DATA)   
  89.             break//失败,退出  
  90.   
  91.         _tprintf( TEXT("%sn"), chBuf ); // 打印读的结果  
  92.     } while (!fSuccess);  //  ERROR_MORE_DATA 或者成功则循环  
  93.   
  94.     getch();//任意键退出  
  95.     // 关闭句柄  
  96.     CloseHandle(hPipe);    
  97.     return 0;   
  98. }  


 

管道服务端代码实现如下,

[cpp]  view plain  copy
  1. /* 头文件 */  
  2. #include <windows.h>   
  3. #include <stdio.h>  
  4. #include <tchar.h>  
  5. /* 常量 */  
  6. #define PIPE_TIMEOUT 5000  
  7. #define BUFSIZE 4096  
  8. /* 结构定义 */  
  9. typedef struct   
  10. {   
  11.     OVERLAPPED oOverlap;   
  12.     HANDLE hPipeInst;   
  13.     TCHAR chRequest[BUFSIZE];   
  14.     DWORD cbRead;  
  15.     TCHAR chReply[BUFSIZE];   
  16.     DWORD cbToWrite;   
  17. } PIPEINST, *LPPIPEINST;   
  18. /* 函数声明 */  
  19. VOID DisconnectAndClose(LPPIPEINST);   
  20. BOOL CreateAndConnectInstance(LPOVERLAPPED);   
  21. BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED);   
  22. VOID GetAnswerToRequest(LPPIPEINST);   
  23. VOID WINAPI CompletedWriteRoutine(DWORDDWORD, LPOVERLAPPED);   
  24. VOID WINAPI CompletedReadRoutine(DWORDDWORD, LPOVERLAPPED);   
  25. /* 全局变量 */  
  26. HANDLE hPipe;   
  27. /* ************************************ 
  28. * int main(VOID)  
  29. * 功能    pipe 通信服务端主函数 
  30. **************************************/  
  31. int main(VOID)   
  32. {   
  33.     HANDLE hConnectEvent;   
  34.     OVERLAPPED oConnect;   
  35.     LPPIPEINST lpPipeInst;   
  36.     DWORD dwWait, cbRet;   
  37.     BOOL fSuccess, fPendingIO;   
  38.   
  39.     // 用于连接操作的事件对象   
  40.     hConnectEvent = CreateEvent(   
  41.         NULL,    // 默认属性  
  42.         TRUE,    // 手工reset  
  43.         TRUE,    // 初始状态 signaled   
  44.         NULL);   // 未命名  
  45.   
  46.     if (hConnectEvent == NULL)   
  47.     {  
  48.         printf("CreateEvent failed with %d.n", GetLastError());   
  49.         return 0;  
  50.     }  
  51.     // OVERLAPPED 事件  
  52.     oConnect.hEvent = hConnectEvent;   
  53.   
  54.     // 创建连接实例,等待连接  
  55.     fPendingIO = CreateAndConnectInstance(&oConnect);   
  56.   
  57.     while (1)   
  58.     {  
  59.         // 等待客户端连接或读写操作完成   
  60.         dwWait = WaitForSingleObjectEx(   
  61.             hConnectEvent,  // 等待的事件   
  62.             INFINITE,       // 无限等待  
  63.             TRUE);         
  64.   
  65.         switch (dwWait)   
  66.         {   
  67.         case 0:       
  68.             // pending   
  69.             if (fPendingIO)   
  70.             {   
  71.                 // 获取 Overlapped I/O 的结果  
  72.                 fSuccess = GetOverlappedResult(   
  73.                     hPipe,     // pipe 句柄   
  74.                     &oConnect, // OVERLAPPED 结构   
  75.                     &cbRet,    // 已经传送的数据量  
  76.                     FALSE);    // 不等待  
  77.                 if (!fSuccess)   
  78.                 {  
  79.                     printf("ConnectNamedPipe (%d)n", GetLastError());   
  80.                     return 0;  
  81.                 }  
  82.             }   
  83.   
  84.             // 分配内存   
  85.             lpPipeInst = (LPPIPEINST) HeapAlloc(GetProcessHeap(),0,sizeof(PIPEINST));   
  86.             if (lpPipeInst == NULL)   
  87.             {  
  88.                 printf("GlobalAlloc failed (%d)n", GetLastError());   
  89.                 return 0;  
  90.             }  
  91.             lpPipeInst->hPipeInst = hPipe;   
  92.   
  93.             // 读和写,注意CompletedWriteRoutine和CompletedReadRoutine的相互调用  
  94.             lpPipeInst->cbToWrite = 0;   
  95.             CompletedWriteRoutine(0, 0, (LPOVERLAPPED) lpPipeInst);   
  96.   
  97.             // 再创建一个连接实例,以响应下一个客户端的连接  
  98.             fPendingIO = CreateAndConnectInstance(   
  99.                 &oConnect);   
  100.             break;   
  101.   
  102.             // 读写完成   
  103.         case WAIT_IO_COMPLETION:   
  104.             break;   
  105.   
  106.         default:   
  107.             {  
  108.                 printf("WaitForSingleObjectEx (%d)n", GetLastError());   
  109.                 return 0;  
  110.             }  
  111.         }   
  112.     }   
  113.     return 0;   
  114. }   
  115.   
  116. /* ************************************ 
  117. * CompletedWriteRoutine  
  118. *   写入pipe操作的完成函数 
  119. *   接口参见FileIOCompletionRoutine回调函数定义 
  120. * 
  121. *   当写操作完成时被调用,开始读另外一个客户端的请求 
  122. **************************************/  
  123. VOID WINAPI CompletedWriteRoutine(  
  124.                                   DWORD dwErr,   
  125.                                   DWORD cbWritten,   
  126.                                   LPOVERLAPPED lpOverLap)   
  127. {   
  128.     LPPIPEINST lpPipeInst;   
  129.     BOOL fRead = FALSE;   
  130.     // 保存overlap实例  
  131.     lpPipeInst = (LPPIPEINST) lpOverLap;   
  132.   
  133. // 如果没有错误  
  134.     if ((dwErr == 0) && (cbWritten == lpPipeInst->cbToWrite))   
  135.     {         
  136.         fRead = ReadFileEx(   
  137.         lpPipeInst->hPipeInst,   
  138.         lpPipeInst->chRequest,   
  139.         BUFSIZE*sizeof(TCHAR),   
  140.         (LPOVERLAPPED) lpPipeInst,   
  141.         // 写读操作完成后,调用CompletedReadRoutine  
  142.         (LPOVERLAPPED_COMPLETION_ROUTINE) CompletedReadRoutine);   
  143.     }     
  144.     if (! fRead)   
  145.         // 出错,断开连接  
  146.         DisconnectAndClose(lpPipeInst);   
  147. }   
  148.   
  149. /* ************************************ 
  150. * CompletedReadRoutine  
  151. *   读取pipe操作的完成函数 
  152. *   接口参见FileIOCompletionRoutine回调函数定义 
  153. * 
  154. *   当读操作完成时被调用,写入回复 
  155. **************************************/  
  156. VOID WINAPI CompletedReadRoutine(  
  157.                                  DWORD dwErr,   
  158.                                  DWORD cbBytesRead,   
  159.                                  LPOVERLAPPED lpOverLap)   
  160. {   
  161.     LPPIPEINST lpPipeInst;   
  162.     BOOL fWrite = FALSE;   
  163.   
  164.     // 保存overlap实例  
  165.     lpPipeInst = (LPPIPEINST) lpOverLap;   
  166.   
  167.     // 如果没有错误  
  168.     if ((dwErr == 0) && (cbBytesRead != 0))   
  169.     {   
  170.         // 根据客户端的请求,生成回复  
  171.         GetAnswerToRequest(lpPipeInst);   
  172.         // 将回复写入到pipe  
  173.         fWrite = WriteFileEx(   
  174.             lpPipeInst->hPipeInst,   
  175.             lpPipeInst->chReply, //将响应写入pipe  
  176.             lpPipeInst->cbToWrite,   
  177.             (LPOVERLAPPED) lpPipeInst,   
  178.             // 写入完成后,调用CompletedWriteRoutine  
  179.             (LPOVERLAPPED_COMPLETION_ROUTINE) CompletedWriteRoutine);   
  180.     }   
  181.   
  182.     if (! fWrite)   
  183.         // 出错,断开连接  
  184.         DisconnectAndClose(lpPipeInst);   
  185. }   
  186.   
  187. /* ************************************ 
  188. * VOID DisconnectAndClose(LPPIPEINST lpPipeInst)  
  189. * 功能    断开一个连接的实例 
  190. * 参数    lpPipeInst,断开并关闭的实例句柄 
  191. **************************************/  
  192. VOID DisconnectAndClose(LPPIPEINST lpPipeInst)   
  193. {   
  194.     // 关闭连接实例  
  195.     if (! DisconnectNamedPipe(lpPipeInst->hPipeInst) )   
  196.     {  
  197.         printf("DisconnectNamedPipe failed with %d.n", GetLastError());  
  198.     }  
  199.     // 关闭 pipe 实例的句柄   
  200.     CloseHandle(lpPipeInst->hPipeInst);   
  201.     // 释放  
  202.     if (lpPipeInst != NULL)   
  203.         HeapFree(GetProcessHeap(),0, lpPipeInst);   
  204. }   
  205.   
  206. /* ************************************ 
  207. * BOOL CreateAndConnectInstance(LPOVERLAPPED lpoOverlap) 
  208. * 功能    建立连接实例 
  209. * 参数    lpoOverlap,用于overlapped IO的结构 
  210. * 返回值   是否成功 
  211. **************************************/  
  212. BOOL CreateAndConnectInstance(LPOVERLAPPED lpoOverlap)   
  213. {   
  214.     LPTSTR lpszPipename = TEXT("\\.\pipe\samplenamedpipe");   
  215.     // 创建named pipe    
  216.     hPipe = CreateNamedPipe(   
  217.         lpszPipename,             // pipe 名   
  218.         PIPE_ACCESS_DUPLEX |      // 可读可写  
  219.         FILE_FLAG_OVERLAPPED,     // overlapped 模式   
  220.         // pipe模式  
  221.         PIPE_TYPE_MESSAGE |       // 消息类型 pipe   
  222.         PIPE_READMODE_MESSAGE |   // 消息读模式   
  223.         PIPE_WAIT,                // 阻塞模式  
  224.         PIPE_UNLIMITED_INSTANCES, // 无限制实例  
  225.         BUFSIZE*sizeof(TCHAR),    // 输出缓存大小  
  226.         BUFSIZE*sizeof(TCHAR),    // 输入缓存大小  
  227.         PIPE_TIMEOUT,             // 客户端超时  
  228.         NULL);                    // 默认安全属性  
  229.     if (hPipe == INVALID_HANDLE_VALUE)   
  230.     {  
  231.         printf("CreateNamedPipe failed with %d.n", GetLastError());   
  232.         return 0;  
  233.     }  
  234.   
  235.     // 连接到新的客户端  
  236.     return ConnectToNewClient(hPipe, lpoOverlap);   
  237. }  
  238.   
  239. /* ************************************ 
  240. * BOOL ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo) 
  241. * 功能    建立连接实例 
  242. * 参数    lpoOverlap,用于overlapped IO的结构 
  243. * 返回值   是否成功 
  244. **************************************/  
  245. BOOL ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo)   
  246. {   
  247.     BOOL fConnected, fPendingIO = FALSE;   
  248.   
  249.     // 开始一个 overlapped 连接   
  250.     fConnected = ConnectNamedPipe(hPipe, lpo);   
  251.   
  252.     if (fConnected)   
  253.     {  
  254.         printf("ConnectNamedPipe failed with %d.n", GetLastError());   
  255.         return 0;  
  256.     }  
  257.     switch (GetLastError())   
  258.     {   
  259.         // overlapped连接进行中.   
  260.     case ERROR_IO_PENDING:   
  261.         fPendingIO = TRUE;   
  262.         break;   
  263.         // 已经连接,因此Event未置位   
  264.     case ERROR_PIPE_CONNECTED:   
  265.         if (SetEvent(lpo->hEvent))   
  266.             break;   
  267.         // error  
  268.     default:   
  269.         {  
  270.             printf("ConnectNamedPipe failed with %d.n", GetLastError());  
  271.             return 0;  
  272.         }  
  273.     }   
  274.     return fPendingIO;   
  275. }  
  276.   
  277. // TODO根据客户端的请求,给出响应  
  278. VOID GetAnswerToRequest(LPPIPEINST pipe)  
  279. {  
  280.     _tprintf( TEXT("[%d] %sn"), pipe->hPipeInst, pipe->chRequest);  
  281.     lstrcpyn( pipe->chReply,  TEXT("Default answer from server") ,BUFSIZE);  
  282.     pipe->cbToWrite = (lstrlen(pipe->chReply)+1)*sizeof(TCHAR);  
  283. }  

最后

以上就是英勇西装为你收集整理的基于visual c++之windows核心编程代码分析(17)通过pipe进程间通信的全部内容,希望文章能够帮你解决基于visual c++之windows核心编程代码分析(17)通过pipe进程间通信所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部