windows命名管道

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

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

0x01 Server端

  代码流程:

  1、创建命名管道:CreateNamedPipe

  2、等待客户端连接:ConnectNamedPipe

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

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

  5、关闭连接:DisconnectNamedPipe

  6、关闭管道:CloseHandle

使用函数:

  CreateNamedPipe创建一个命名的管道

HANDLE CreateNamedPipe(
  LPCTSTR lpName,                             // 管道名称,形式必须为\\.\pipe\pipeName
  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\n"), 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;">\\.\pipe\pipeName</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\n"), chBuf);
100         //printf("%S\n", chBuf);
101     } while (!fSuccess);  // repeat loop if ERROR_MORE_DATA
102
103     getch();
104
105     CloseHandle(hPipe);
106
107     return 0;
108 }

NamedPipeClient

时间: 2024-10-27 08:04:50

windows命名管道的相关文章

windows namedPipe 命名管道clent and server

1.client: 1 #include "iostream" 2 #include "windows.h" 3 4 using namespace std; 5 void main(int argc,char* argv[]) 6 { 7 LPCTSTR Message="the pipe's message from a client to server."; 8 if(argc==2) 9 Message=argv[1]; 10 DWORD

Windows进程间通信—命名管道

命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节.我们在不了解网络协议的情况下,也可以利用命名管道来实现进程间的通信.与Socket网络通信相比,命名管道不再需要编写身份验证的代码.将命名管道作为一种网络编程方案时,它实际上建立了一个C/S通信体系,并在其中可靠的传输数据.命名管道服务器和客户机的区别在于:服务器是唯一一个有权创建命名管道的进程,也只有它能接受管道客户机的连接请求.而客户机只能同一个现成的命名管道服务器建立连接.命名管道服务器只能在WindowsNT或Window

Windows进程间通信--命名管道

1.相关概述 命名管道(Named Pipes)是一种简单的进程间通信(IPC)机制.命名管道可以在同一台计算机的不同进程之间,或者跨越一个网络的不同计算机的不同进程之间的可靠的双向或单向的数据通信. 命名管道利用了微软网络提供者(MSNP)重定向器,因此无需涉及底层的通信协议等细节.命名管道是围绕windows文件系统设计的一种机制,采用"命名管道文件系统"(Named Pipe File System,NPFS)接口.因此,客户端和服务端均可以使用标准的WIN32文件系统API函数

C#中使用命名管道进行进程通信的实例

原文:C#中使用命名管道进行进程通信的实例 1 新建解决方案NamedPipeExample 在解决方案下面新建两个项目:Client和Server,两者的输出类型均为"Windows 应用程序".整个程序的结构如下图所示. 2 实现项目Client Client仅包含一个名为"客户端"的窗体,如下图所示. 编写窗体后端代码,如下所示. using System; using System.IO; using System.IO.Pipes; using Syste

C#命名管道通信

原文:C#命名管道通信 C#命名管道通信 最近项目中要用c#进程间通信,以前常见的方法包括RMI.发消息等.但在Windows下面发消息需要有窗口,我们的程序是一个后台运行程序,发消息不试用.RMI又用的太多了,准备用管道通信来做消息通信. 管道通信以前在大学学过,包括匿名管道和命名管道.匿名管道只能用在父子进程之间:命名管道可以用在两个进程甚至跨服务器通信.这里给出命名管道的示例. 服务器端代码 private static void WaitData() { using (NamedPipe

命名管道-简单的例子

#include "stdafx.h" #include<iostream> #include<windows.h> #include<ctime> using namespace std; DWORD WINAPI thread1(LPVOID param) { char buf[256]; DWORD rlen=0; HANDLE hPipe = CreateNamedPipe(TEXT("\\\\.\\Pipe\\mypipe&quo

Unidac连接出错:命名管道提供程序:管道的另一端上无任何进程.

环境: DELPHI XE ,UniDAC 6.2.8, (Options->Provider=prNativeClient) 程序编译后,放在Windows Server 2003 (sp2 32位)上运行, 连接MSSQL2005(32位)时报以下错误: 命名管道提供程序:管道的另一端上无任何进程. 确定SQL Server Native Client 驱动已经安装.   解决:启用Named Pipes 协议即可.

命名管道-MSDN例子

服务器: 1 #include "stdafx.h" 2 #include <windows.h> 3 #include <stdio.h> 4 #include <tchar.h> 5 #include <strsafe.h> 6 7 #define BUFSIZE 512 8 9 DWORD WINAPI InstanceThread(LPVOID); 10 VOID GetAnswerToRequest(LPTSTR, LPTSTR

命名管道与匿名管道

匿名管道 父进程 #include<windows.h>#include<stdio.h>main(){ HANDLE read=NULL,write=NULL;//定义两句柄 SECURITY_ATTRIBUTES ss;  STARTUPINFO sa={0};  PROCESS_INFORMATION pp={0};      //定义结构体SECURITY_ATTRIBUTES变量 char text[]="匿名管道程序测试!"; DWORD write