zoukankan      html  css  js  c++  java
  • windows命名管道

      命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节。

      将命名管道作为一种网络编程方案时,它实际上建立了一个C/S通信体系,并在其中可靠的传输数据。命名管道服务器和客户机的区别在于:服务器是唯一一个有权创建命名管道的进程,也只有它能接受管道客户机的连接请求。而客户机只能同一个现成的命名管道服务器建立连接。命名管道提供了两种基本通信模式,字节模式和消息模式。在字节模式中,数据以一个连续的字节流的形式在客户机和服务器之间流动。而在消息模式中,客户机和服务器则通过一系列不连续的数据单位进行数据的收发,每次在管道上发出一条消息后,它必须作为一条完整的消息读入。

    0x01 Server端

      代码流程:

      1、创建命名管道:CreateNamedPipe

      2、等待客户端连接:ConnectNamedPipe

      3、读取客户端请求数据:ReadFile

      4、向客户端回复数据:WriteFile

      5、关闭连接:DisconnectNamedPipe

      6、关闭管道:CloseHandle

           使用函数:

      CreateNamedPipe创建一个命名的管道

    HANDLE CreateNamedPipe(  
      LPCTSTR lpName,                             // 管道名称,形式必须为\.pipepipeName  
      DWORD dwOpenMode,                           // 打开管道的模式  
      DWORD dwPipeMode,                           // 管道的模式,传输数据的形式  
      DWORD nMaxInstances,                        // 最大连接客户端的个数  
      DWORD nOutBufferSize,                       // 输出缓冲区的大小  
      DWORD nInBufferSize,                        // 输入缓冲区的大小  
      DWORD nDefaultTimeOut,                      // 默认的超时时间  
      LPSECURITY_ATTRIBUTES lpSecurityAttributes  // 安全属性,一般为NULL  
    );  
    

      ConnectNamedPipe等待一个客户端的连接

    BOOL ConnectNamedPipe(    
      HANDLE hNamedPipe,          // 命名管道对象  
      LPOVERLAPPED lpOverlapped   // OVERLAPPED结构  
    );  
    

      通信的操作跟我们的文件操作是一样的,通过ReadFile和WriteFile来进行读和写。

      通信完之后,调用DisconnectNamedPipe来进行断开连接

    BOOL DisconnectNamedPipe(    
      HANDLE hNamedPipe   // 命名管道对象  
    );  
    

      

      Server端源码:

      1 // NamedPipeServer.cpp : 定义控制台应用程序的入口点。
      2 //
      3 #include "stdafx.h"  
      4 #include <windows.h>  
      5 #include <strsafe.h>  
      6 
      7 #define BUFSIZE 4096  
      8 
      9 DWORD WINAPI InstanceThread(LPVOID);
     10 VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD);
     11 
     12 int _tmain(VOID)
     13 {
     14     BOOL fConnected;
     15     DWORD dwThreadId;
     16     HANDLE hPipe, hThread;
     17     LPTSTR lpszPipename = TEXT("\\.\pipe\LiudadaNemaedPipe");
     18 
     19     // The main loop creates an instance of the named pipe and   
     20     // then waits for a client to connect to it. When the client   
     21     // connects, a thread is created to handle communications   
     22     // with that client, and the loop is repeated.   
     23 
     24     for (;;)
     25     {
     26         hPipe = CreateNamedPipe(
     27             lpszPipename,             // pipe name            指向管道名称的指针
     28             PIPE_ACCESS_DUPLEX,       // read/write access    管道打开模式
     29             PIPE_TYPE_MESSAGE |       // message type pipe    管道模式
     30             PIPE_READMODE_MESSAGE |   // message-read mode   
     31             PIPE_WAIT,                // blocking mode   
     32             PIPE_UNLIMITED_INSTANCES, // max. instances       最大实例数 
     33             BUFSIZE,                  // output buffer size   输出缓存大小
     34             BUFSIZE,                  // input buffer size    输入缓存大小
     35             0,                        // client time-out      超时设置
     36             NULL);                    // default security attribute   
     37 
     38         if (hPipe == INVALID_HANDLE_VALUE)
     39         {
     40             printf("CreatePipe failed");
     41             return 0;
     42         }
     43 
     44         // Wait for the client to connect; if it succeeds,   
     45         // the function returns a nonzero value. If the function  
     46         // returns zero, GetLastError returns ERROR_PIPE_CONNECTED.   
     47 
     48         fConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
     49 
     50         if (fConnected)
     51         {
     52             // Create a thread for this client.   
     53             hThread = CreateThread(
     54                 NULL,              // no security attribute   
     55                 0,                 // default stack size   
     56                 InstanceThread,    // thread proc  
     57                 (LPVOID)hPipe,    // thread parameter   
     58                 0,                 // not suspended   
     59                 &dwThreadId);      // returns thread ID   
     60 
     61             if (hThread == NULL)
     62             {
     63                 printf("CreateThread failed");
     64                 return 0;
     65             }
     66             else CloseHandle(hThread);
     67         }
     68         else
     69         {
     70             // The client could not connect, so close the pipe.   
     71             CloseHandle(hPipe);
     72         }
     73     }
     74     return 1;
     75 }
     76 
     77 DWORD WINAPI InstanceThread(LPVOID lpvParam)
     78 {
     79     TCHAR chRequest[BUFSIZE];
     80     TCHAR chReply[BUFSIZE];
     81     DWORD cbBytesRead, cbReplyBytes, cbWritten;
     82     BOOL fSuccess;
     83     HANDLE hPipe;
     84 
     85     // The thread's parameter is a handle to a pipe instance.   
     86 
     87     hPipe = (HANDLE)lpvParam;
     88 
     89     while (1)
     90     {
     91         // Read client requests from the pipe.   
     92         fSuccess = ReadFile(
     93             hPipe,        // handle to pipe   
     94             chRequest,    // buffer to receive data   
     95             BUFSIZE * sizeof(TCHAR), // size of buffer   
     96             &cbBytesRead, // number of bytes read   
     97             NULL);        // not overlapped I/O   
     98 
     99         if (!fSuccess || cbBytesRead == 0)
    100             break;
    101         printf((const char*)chRequest);
    102 
    103         GetAnswerToRequest(chRequest, chReply, &cbReplyBytes);
    104 
    105         // Write the reply to the pipe.   
    106         fSuccess = WriteFile(
    107             hPipe,        // handle to pipe   
    108             chReply,      // buffer to write from   
    109             cbReplyBytes, // number of bytes to write   
    110             &cbWritten,   // number of bytes written   
    111             NULL);        // not overlapped I/O   
    112 
    113         if (!fSuccess || cbReplyBytes != cbWritten) break;
    114     }
    115 
    116     // Flush the pipe to allow the client to read the pipe's contents   
    117     // before disconnecting. Then disconnect the pipe, and close the   
    118     // handle to this pipe instance.   
    119 
    120     FlushFileBuffers(hPipe);
    121     DisconnectNamedPipe(hPipe);
    122     CloseHandle(hPipe);
    123 
    124     return 1;
    125 }
    126 
    127 VOID GetAnswerToRequest(LPTSTR chRequest,
    128     LPTSTR chReply, LPDWORD pchBytes)
    129 {
    130     _tprintf(TEXT("%s
    "), chRequest);
    131     StringCchCopy(chReply, BUFSIZE, TEXT("Message from server"));
    132     *pchBytes = (lstrlen(chReply) + 1) * sizeof(TCHAR);
    133 }
    NamedPipeServer

      

    0x01 Client端

      代码流程:

      1、打开命名管道:CreateFile

      2、等待服务端响应:WaitNamedPipe

      3、切换管道为读模式:SetNamedPipeHandleState

      4、向服务端发数据:WriteFile

      5、读服务端返回的数据:ReadFile

      6、关闭管道:CloseHandle

      WaitNamedPipe来检查一下,命名管道是否存在:

    BOOL WaitNamedPipe(    
      LPCTSTR lpNamedPipeName,  // 管道名称,形式必须为<span style="font-family: Arial, Helvetica, sans-serif;">\.pipepipeName</span>  
      DWORD nTimeOut            // 超时时间,给NULL为默认的超时时间  
    );  
    

      SetNamedPipeHandleState 设置管道的一些参数,传输模式

    BOOL WINAPI SetNamedPipeHandleState(
      _In_      HANDLE hNamedPipe,//命名管道句柄
      _In_opt_  LPDWORD lpMode,//传输模式,字节流或者信息流
      _In_opt_  LPDWORD lpMaxCollectionCount,//最大字节数
      _In_opt_  LPDWORD lpCollectDataTimeout//超时
    );
    

      

    Client端源码:

      1 // NamedPipeClient.cpp : 定义控制台应用程序的入口点。
      2 //
      3 
      4 #include "stdafx.h"  
      5 #include <windows.h>  
      6 #include <conio.h>  
      7 #define BUFSIZE 512  
      8 
      9 int main(int argc, TCHAR *argv[])
     10 {
     11     HANDLE hPipe;
     12     LPTSTR lpvMessage = TEXT("Message from client");
     13     TCHAR chBuf[BUFSIZE];
     14     BOOL fSuccess;
     15     DWORD cbRead, cbWritten, dwMode;
     16     LPTSTR lpszPipename = TEXT("\\.\pipe\LiudadaNemaedPipe");
     17 
     18     if (argc > 1)
     19         lpvMessage = argv[1];
     20 
     21     // Try to open a named pipe; wait for it, if necessary.   
     22 
     23     while (1)
     24     {
     25         hPipe = CreateFile(
     26             lpszPipename,   // pipe name   
     27             GENERIC_READ |  // read and write access   
     28             GENERIC_WRITE,
     29             0,              // no sharing   
     30             NULL,           // default security attributes  
     31             OPEN_EXISTING,  // opens existing pipe   
     32             0,              // default attributes   
     33             NULL);          // no template file   
     34 
     35                             // Break if the pipe handle is valid.   
     36 
     37         if (hPipe != INVALID_HANDLE_VALUE)
     38             break;
     39 
     40         // Exit if an error other than ERROR_PIPE_BUSY occurs.   
     41 
     42         if (GetLastError() != ERROR_PIPE_BUSY)
     43         {
     44             printf("Could not open pipe");
     45             return 0;
     46         }
     47 
     48         // All pipe instances are busy, so wait for 20 seconds.   
     49 
     50         if (!WaitNamedPipe(lpszPipename, 20000))
     51         {
     52             printf("Could not open pipe");
     53             return 0;
     54         }
     55     }
     56 
     57     // The pipe connected; change to message-read mode.   
     58 
     59     dwMode = PIPE_READMODE_MESSAGE;
     60     fSuccess = SetNamedPipeHandleState(
     61         hPipe,    // pipe handle   
     62         &dwMode,  // new pipe mode   
     63         NULL,     // don't set maximum bytes   
     64         NULL);    // don't set maximum time   
     65     if (!fSuccess)
     66     {
     67         printf("SetNamedPipeHandleState failed");
     68         return 0;
     69     }  
     70 
     71        // Send a message to the pipe server.   
     72 
     73     fSuccess = WriteFile(
     74         hPipe,                  // pipe handle   
     75         lpvMessage,             // message   
     76         (lstrlen(lpvMessage) + 1) * sizeof(TCHAR), // message length   
     77         &cbWritten,             // bytes written   
     78         NULL);                  // not overlapped   
     79     if (!fSuccess)
     80     {
     81         printf("WriteFile failed");
     82         return 0;
     83     }
     84 
     85     do
     86     {
     87         // Read from the pipe.   
     88                  
     89         fSuccess = ReadFile(
     90             hPipe,    // pipe handle   
     91             chBuf,    // buffer to receive reply   
     92             BUFSIZE * sizeof(TCHAR),  // size of buffer   
     93             &cbRead,  // number of bytes read   
     94             NULL);    // not overlapped   
     95 
     96         if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
     97             break;
     98 
     99         _tprintf(TEXT("%s
    "), chBuf);
    100         //printf("%S
    ", chBuf);
    101     } while (!fSuccess);  // repeat loop if ERROR_MORE_DATA   
    102 
    103     getch();
    104 
    105     CloseHandle(hPipe);
    106 
    107     return 0;
    108 }
    NamedPipeClient
  • 相关阅读:
    长沙雅礼中学集训-------------------day1(内含day0)
    17年 5月份刷题版
    manecher_回文串;
    后缀数组
    湖南集训
    好像又好久没更了;计算课noip模拟赛;
    dp的练习题;
    oj1638
    【noi】植物大战僵尸
    #日常吐槽
  • 原文地址:https://www.cnblogs.com/lsh123/p/7435401.html
Copyright © 2011-2022 走看看