命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节。
将命名管道作为一种网络编程方案时,它实际上建立了一个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端源码:
<span> 1</span>
<span>//</span>
<span> NamedPipeServer.cpp : 定义控制台应用程序的入口点。
</span>
<span> 2</span>
<span>//
</span>
<span> 3</span> #include <span>"</span><span>stdafx.h</span><span>"</span><span> 4</span> #include <windows.h>
<span> 5</span> #include <strsafe.h>
<span> 6</span><span> 7</span><span>#define</span> BUFSIZE 4096
<span> 8</span><span> 9</span><span>DWORD WINAPI InstanceThread(LPVOID);
</span><span> 10</span><span>VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD);
</span><span> 11</span><span> 12</span><span>int</span><span> _tmain(VOID)
</span><span> 13</span><span>{
</span><span> 14</span><span> BOOL fConnected;
</span><span> 15</span><span> DWORD dwThreadId;
</span><span> 16</span><span> HANDLE hPipe, hThread;
</span><span> 17</span> LPTSTR lpszPipename = TEXT(<span>"</span><span>\.pipeLiudadaNemaedPipe</span><span>"</span><span>);
</span><span> 18</span><span> 19</span><span>//</span><span> The main loop creates an instance of the named pipe and
</span><span> 20</span><span>//</span><span> then waits for a client to connect to it. When the client
</span><span> 21</span><span>//</span><span> connects, a thread is created to handle communications
</span><span> 22</span><span>//</span><span> with that client, and the loop is repeated. </span><span> 23</span><span> 24</span><span>for</span><span> (;;)
</span><span> 25</span><span> {
</span><span> 26</span> hPipe =<span> CreateNamedPipe(
</span><span> 27</span> lpszPipename, <span>//</span><span> pipe name 指向管道名称的指针</span><span> 28</span> PIPE_ACCESS_DUPLEX, <span>//</span><span> read/write access 管道打开模式</span><span> 29</span> PIPE_TYPE_MESSAGE | <span>//</span><span> message type pipe 管道模式</span><span> 30</span> PIPE_READMODE_MESSAGE | <span>//</span><span> message-read mode </span><span> 31</span> PIPE_WAIT, <span>//</span><span> blocking mode </span><span> 32</span> PIPE_UNLIMITED_INSTANCES, <span>//</span><span> max. instances 最大实例数 </span><span> 33</span> BUFSIZE, <span>//</span><span> output buffer size 输出缓存大小</span><span> 34</span> BUFSIZE, <span>//</span><span> input buffer size 输入缓存大小</span><span> 35</span><span>0</span>, <span>//</span><span> client time-out 超时设置</span><span> 36</span> NULL); <span>//</span><span> default security attribute </span><span> 37</span><span> 38</span><span>if</span> (hPipe ==<span> INVALID_HANDLE_VALUE)
</span><span> 39</span><span> {
</span><span> 40</span> printf(<span>"</span><span>CreatePipe failed</span><span>"</span><span>);
</span><span> 41</span><span>return</span><span>0</span><span>;
</span><span> 42</span><span> }
</span><span> 43</span><span> 44</span><span>//</span><span> Wait for the client to connect; if it succeeds,
</span><span> 45</span><span>//</span><span> the function returns a nonzero value. If the function
</span><span> 46</span><span>//</span><span> returns zero, GetLastError returns ERROR_PIPE_CONNECTED. </span><span> 47</span><span> 48</span> fConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() ==<span> ERROR_PIPE_CONNECTED);
</span><span> 49</span><span> 50</span><span>if</span><span> (fConnected)
</span><span> 51</span><span> {
</span><span> 52</span><span>//</span><span> Create a thread for this client. </span><span> 53</span> hThread =<span> CreateThread(
</span><span> 54</span> NULL, <span>//</span><span> no security attribute </span><span> 55</span><span>0</span>, <span>//</span><span> default stack size </span><span> 56</span> InstanceThread, <span>//</span><span> thread proc </span><span> 57</span> (LPVOID)hPipe, <span>//</span><span> thread parameter </span><span> 58</span><span>0</span>, <span>//</span><span> not suspended </span><span> 59</span> &dwThreadId); <span>//</span><span> returns thread ID </span><span> 60</span><span> 61</span><span>if</span> (hThread ==<span> NULL)
</span><span> 62</span><span> {
</span><span> 63</span> printf(<span>"</span><span>CreateThread failed</span><span>"</span><span>);
</span><span> 64</span><span>return</span><span>0</span><span>;
</span><span> 65</span><span> }
</span><span> 66</span><span>else</span><span> CloseHandle(hThread);
</span><span> 67</span><span> }
</span><span> 68</span><span>else</span><span> 69</span><span> {
</span><span> 70</span><span>//</span><span> The client could not connect, so close the pipe. </span><span> 71</span><span> CloseHandle(hPipe);
</span><span> 72</span><span> }
</span><span> 73</span><span> }
</span><span> 74</span><span>return</span><span>1</span><span>;
</span><span> 75</span><span>}
</span><span> 76</span><span> 77</span><span>DWORD WINAPI InstanceThread(LPVOID lpvParam)
</span><span> 78</span><span>{
</span><span> 79</span><span> TCHAR chRequest[BUFSIZE];
</span><span> 80</span><span> TCHAR chReply[BUFSIZE];
</span><span> 81</span><span> DWORD cbBytesRead, cbReplyBytes, cbWritten;
</span><span> 82</span><span> BOOL fSuccess;
</span><span> 83</span><span> HANDLE hPipe;
</span><span> 84</span><span> 85</span><span>//</span><span> The thread‘s parameter is a handle to a pipe instance. </span><span> 86</span><span> 87</span> hPipe =<span> (HANDLE)lpvParam;
</span><span> 88</span><span> 89</span><span>while</span> (<span>1</span><span>)
</span><span> 90</span><span> {
</span><span> 91</span><span>//</span><span> Read client requests from the pipe. </span><span> 92</span> fSuccess =<span> ReadFile(
</span><span> 93</span> hPipe, <span>//</span><span> handle to pipe </span><span> 94</span> chRequest, <span>//</span><span> buffer to receive data </span><span> 95</span> BUFSIZE * <span>sizeof</span>(TCHAR), <span>//</span><span> size of buffer </span><span> 96</span> &cbBytesRead, <span>//</span><span> number of bytes read </span><span> 97</span> NULL); <span>//</span><span> not overlapped I/O </span><span> 98</span><span> 99</span><span>if</span> (!fSuccess || cbBytesRead == <span>0</span><span>)
</span><span>100</span><span>break</span><span>;
</span><span>101</span> printf((<span>const</span><span>char</span>*<span>)chRequest);
</span><span>102</span><span>103</span> GetAnswerToRequest(chRequest, chReply, &<span>cbReplyBytes);
</span><span>104</span><span>105</span><span>//</span><span> Write the reply to the pipe. </span><span>106</span> fSuccess =<span> WriteFile(
</span><span>107</span> hPipe, <span>//</span><span> handle to pipe </span><span>108</span> chReply, <span>//</span><span> buffer to write from </span><span>109</span> cbReplyBytes, <span>//</span><span> number of bytes to write </span><span>110</span> &cbWritten, <span>//</span><span> number of bytes written </span><span>111</span> NULL); <span>//</span><span> not overlapped I/O </span><span>112</span><span>113</span><span>if</span> (!fSuccess || cbReplyBytes != cbWritten) <span>break</span><span>;
</span><span>114</span><span> }
</span><span>115</span><span>116</span><span>//</span><span> Flush the pipe to allow the client to read the pipe‘s contents
</span><span>117</span><span>//</span><span> before disconnecting. Then disconnect the pipe, and close the
</span><span>118</span><span>//</span><span> handle to this pipe instance. </span><span>119</span><span>120</span><span> FlushFileBuffers(hPipe);
</span><span>121</span><span> DisconnectNamedPipe(hPipe);
</span><span>122</span><span> CloseHandle(hPipe);
</span><span>123</span><span>124</span><span>return</span><span>1</span><span>;
</span><span>125</span><span>}
</span><span>126</span><span>127</span><span>VOID GetAnswerToRequest(LPTSTR chRequest,
</span><span>128</span><span> LPTSTR chReply, LPDWORD pchBytes)
</span><span>129</span><span>{
</span><span>130</span> _tprintf(TEXT(<span>"</span><span>%s
</span><span>"</span><span>), chRequest);
</span><span>131</span> StringCchCopy(chReply, BUFSIZE, TEXT(<span>"</span><span>Message from server</span><span>"</span><span>));
</span><span>132</span> *pchBytes = (lstrlen(chReply) + <span>1</span>) * <span>sizeof</span><span>(TCHAR);
</span><span>133</span> }
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端源码:
<span> 1</span>
<span>//</span>
<span> NamedPipeClient.cpp : 定义控制台应用程序的入口点。
</span>
<span> 2</span>
<span>//
</span>
<span> 3</span>
<span> 4</span> #include <span>"</span><span>stdafx.h</span><span>"</span><span> 5</span> #include <windows.h>
<span> 6</span> #include <conio.h>
<span> 7</span><span>#define</span> BUFSIZE 512
<span> 8</span><span> 9</span><span>int</span> main(<span>int</span> argc, TCHAR *<span>argv[])
</span><span> 10</span><span>{
</span><span> 11</span><span> HANDLE hPipe;
</span><span> 12</span> LPTSTR lpvMessage = TEXT(<span>"</span><span>Message from client</span><span>"</span><span>);
</span><span> 13</span><span> TCHAR chBuf[BUFSIZE];
</span><span> 14</span><span> BOOL fSuccess;
</span><span> 15</span><span> DWORD cbRead, cbWritten, dwMode;
</span><span> 16</span> LPTSTR lpszPipename = TEXT(<span>"</span><span>\.pipeLiudadaNemaedPipe</span><span>"</span><span>);
</span><span> 17</span><span> 18</span><span>if</span> (argc > <span>1</span><span>)
</span><span> 19</span> lpvMessage = argv[<span>1</span><span>];
</span><span> 20</span><span> 21</span><span>//</span><span> Try to open a named pipe; wait for it, if necessary. </span><span> 22</span><span> 23</span><span>while</span> (<span>1</span><span>)
</span><span> 24</span><span> {
</span><span> 25</span> hPipe =<span> CreateFile(
</span><span> 26</span> lpszPipename, <span>//</span><span> pipe name </span><span> 27</span> GENERIC_READ | <span>//</span><span> read and write access </span><span> 28</span><span> GENERIC_WRITE,
</span><span> 29</span><span>0</span>, <span>//</span><span> no sharing </span><span> 30</span> NULL, <span>//</span><span> default security attributes </span><span> 31</span> OPEN_EXISTING, <span>//</span><span> opens existing pipe </span><span> 32</span><span>0</span>, <span>//</span><span> default attributes </span><span> 33</span> NULL); <span>//</span><span> no template file
</span><span> 34</span><span> 35</span><span>//</span><span> Break if the pipe handle is valid. </span><span> 36</span><span> 37</span><span>if</span> (hPipe !=<span> INVALID_HANDLE_VALUE)
</span><span> 38</span><span>break</span><span>;
</span><span> 39</span><span> 40</span><span>//</span><span> Exit if an error other than ERROR_PIPE_BUSY occurs. </span><span> 41</span><span> 42</span><span>if</span> (GetLastError() !=<span> ERROR_PIPE_BUSY)
</span><span> 43</span><span> {
</span><span> 44</span> printf(<span>"</span><span>Could not open pipe</span><span>"</span><span>);
</span><span> 45</span><span>return</span><span>0</span><span>;
</span><span> 46</span><span> }
</span><span> 47</span><span> 48</span><span>//</span><span> All pipe instances are busy, so wait for 20 seconds. </span><span> 49</span><span> 50</span><span>if</span> (!WaitNamedPipe(lpszPipename, <span>20000</span><span>))
</span><span> 51</span><span> {
</span><span> 52</span> printf(<span>"</span><span>Could not open pipe</span><span>"</span><span>);
</span><span> 53</span><span>return</span><span>0</span><span>;
</span><span> 54</span><span> }
</span><span> 55</span><span> }
</span><span> 56</span><span> 57</span><span>//</span><span> The pipe connected; change to message-read mode. </span><span> 58</span><span> 59</span> dwMode =<span> PIPE_READMODE_MESSAGE;
</span><span> 60</span> fSuccess =<span> SetNamedPipeHandleState(
</span><span> 61</span> hPipe, <span>//</span><span> pipe handle </span><span> 62</span> &dwMode, <span>//</span><span> new pipe mode </span><span> 63</span> NULL, <span>//</span><span> don‘t set maximum bytes </span><span> 64</span> NULL); <span>//</span><span> don‘t set maximum time </span><span> 65</span><span>if</span> (!<span>fSuccess)
</span><span> 66</span><span> {
</span><span> 67</span> printf(<span>"</span><span>SetNamedPipeHandleState failed</span><span>"</span><span>);
</span><span> 68</span><span>return</span><span>0</span><span>;
</span><span> 69</span><span> }
</span><span> 70</span><span> 71</span><span>//</span><span> Send a message to the pipe server. </span><span> 72</span><span> 73</span> fSuccess =<span> WriteFile(
</span><span> 74</span> hPipe, <span>//</span><span> pipe handle </span><span> 75</span> lpvMessage, <span>//</span><span> message </span><span> 76</span> (lstrlen(lpvMessage) + <span>1</span>) * <span>sizeof</span>(TCHAR), <span>//</span><span> message length </span><span> 77</span> &cbWritten, <span>//</span><span> bytes written </span><span> 78</span> NULL); <span>//</span><span> not overlapped </span><span> 79</span><span>if</span> (!<span>fSuccess)
</span><span> 80</span><span> {
</span><span> 81</span> printf(<span>"</span><span>WriteFile failed</span><span>"</span><span>);
</span><span> 82</span><span>return</span><span>0</span><span>;
</span><span> 83</span><span> }
</span><span> 84</span><span> 85</span><span>do</span><span> 86</span><span> {
</span><span> 87</span><span>//</span><span> Read from the pipe. </span><span> 88</span><span> 89</span> fSuccess =<span> ReadFile(
</span><span> 90</span> hPipe, <span>//</span><span> pipe handle </span><span> 91</span> chBuf, <span>//</span><span> buffer to receive reply </span><span> 92</span> BUFSIZE * <span>sizeof</span>(TCHAR), <span>//</span><span> size of buffer </span><span> 93</span> &cbRead, <span>//</span><span> number of bytes read </span><span> 94</span> NULL); <span>//</span><span> not overlapped </span><span> 95</span><span> 96</span><span>if</span> (!fSuccess && GetLastError() !=<span> ERROR_MORE_DATA)
</span><span> 97</span><span>break</span><span>;
</span><span> 98</span><span> 99</span> _tprintf(TEXT(<span>"</span><span>%s
</span><span>"</span><span>), chBuf);
</span><span>100</span><span>//</span><span>printf("%S
", chBuf);</span><span>101</span> } <span>while</span> (!fSuccess); <span>//</span><span> repeat loop if ERROR_MORE_DATA </span><span>102</span><span>103</span><span> getch();
</span><span>104</span><span>105</span><span> CloseHandle(hPipe);
</span><span>106</span><span>107</span><span>return</span><span>0</span><span>;
</span><span>108</span> }
原文:http://www.cnblogs.com/lsh123/p/7435401.html
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!