服务器:
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, LPDWORD);
11
12 int _tmain(VOID)
13 {
14 BOOL fConnected = FALSE;
15 DWORD dwThreadId = 0;
16 HANDLE hPipe = INVALID_HANDLE_VALUE, hThread = NULL;
17 LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
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 this loop is free to wait for the
23 // next client connect request. It is an infinite loop.
24
25 for (;;)
26 {
27 _tprintf( TEXT("\nPipe Server: Main thread awaiting client connection on %s\n"), lpszPipename);
28 hPipe = CreateNamedPipe(
29 lpszPipename, // pipe name
30 PIPE_ACCESS_DUPLEX, // read/write access
31 PIPE_TYPE_MESSAGE | // message type pipe
32 PIPE_READMODE_MESSAGE | // message-read mode
33 PIPE_WAIT, // blocking mode
34 PIPE_UNLIMITED_INSTANCES, // max. instances
35 BUFSIZE, // output buffer size
36 BUFSIZE, // input buffer size
37 0, // client time-out
38 NULL); // default security attribute
39
40 if (hPipe == INVALID_HANDLE_VALUE)
41 {
42 _tprintf(TEXT("CreateNamedPipe failed, GLE=%d.\n"), GetLastError());
43 return -1;
44 }
45
46 // Wait for the client to connect; if it succeeds,
47 // the function returns a nonzero value. If the function
48 // returns zero, GetLastError returns ERROR_PIPE_CONNECTED.
49
50 //等待客户端接入(目前为阻塞模式)
51 fConnected = ConnectNamedPipe(hPipe, NULL) ?
52 TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
53
54 if (fConnected)
55 {
56 printf("Client connected, creating a processing thread.\n");
57
58 // Create a thread for this client.
59 hThread = CreateThread(
60 NULL, // no security attribute
61 0, // default stack size
62 InstanceThread, // thread proc
63 (LPVOID) hPipe, // thread parameter
64 0, // not suspended
65 &dwThreadId); // returns thread ID
66
67 if (hThread == NULL)
68 {
69 _tprintf(TEXT("CreateThread failed, GLE=%d.\n"), GetLastError());
70 return -1;
71 }
72 else CloseHandle(hThread);
73 }
74 else
75 // The client could not connect, so close the pipe.
76 CloseHandle(hPipe);
77
78 }
79
80 return 0;
81 }
82
83 DWORD WINAPI InstanceThread(LPVOID lpvParam)
84 // This routine is a thread processing function to read from and reply to a client
85 // via the open pipe connection passed from the main loop. Note this allows
86 // the main loop to continue executing, potentially creating more threads of
87 // of this procedure to run concurrently, depending on the number of incoming
88 // client connections.
89 {
90 HANDLE hHeap = GetProcessHeap();
91 TCHAR* pchRequest = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZE*sizeof(TCHAR));
92 TCHAR* pchReply = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZE*sizeof(TCHAR));
93
94 DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
95 BOOL fSuccess = FALSE;
96 HANDLE hPipe = NULL;
97
98 // Do some extra error checking since the app will keep running even if this
99 // thread fails.
100
101 if (lpvParam == NULL)
102 {
103 printf( "\nERROR - Pipe Server Failure:\n");
104 printf( " InstanceThread got an unexpected NULL value in lpvParam.\n");
105 printf( " InstanceThread exitting.\n");
106 if (pchReply != NULL) HeapFree(hHeap, 0, pchReply);
107 if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest);
108 return (DWORD)-1;
109 }
110
111 if (pchRequest == NULL)
112 {
113 printf( "\nERROR - Pipe Server Failure:\n");
114 printf( " InstanceThread got an unexpected NULL heap allocation.\n");
115 printf( " InstanceThread exitting.\n");
116 if (pchReply != NULL) HeapFree(hHeap, 0, pchReply);
117 return (DWORD)-1;
118 }
119
120 if (pchReply == NULL)
121 {
122 printf( "\nERROR - Pipe Server Failure:\n");
123 printf( " InstanceThread got an unexpected NULL heap allocation.\n");
124 printf( " InstanceThread exitting.\n");
125 if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest);
126 return (DWORD)-1;
127 }
128
129 // Print verbose messages. In production code, this should be for debugging only.
130 printf("InstanceThread created, receiving and processing messages.\n");
131
132 // The thread‘s parameter is a handle to a pipe object instance.
133
134 hPipe = (HANDLE) lpvParam;
135
136 // Loop until done reading
137 while (1)
138 {
139 // Read client requests from the pipe. This simplistic code only allows messages
140 // up to BUFSIZE characters in length.
141 fSuccess = ReadFile(
142 hPipe, // handle to pipe
143 pchRequest, // buffer to receive data
144 BUFSIZE*sizeof(TCHAR), // size of buffer
145 &cbBytesRead, // number of bytes read
146 NULL); // not overlapped I/O
147
148 if (!fSuccess || cbBytesRead == 0)
149 {
150 if (GetLastError() == ERROR_BROKEN_PIPE)
151 {
152 _tprintf(TEXT("InstanceThread: client disconnected.\n"), GetLastError());
153 }
154 else
155 {
156 _tprintf(TEXT("InstanceThread ReadFile failed, GLE=%d.\n"), GetLastError());
157 }
158 break;
159 }
160
161 // Process the incoming message.
162 GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes);
163
164 // Write the reply to the pipe.
165 fSuccess = WriteFile(
166 hPipe, // handle to pipe
167 pchReply, // buffer to write from
168 cbReplyBytes, // number of bytes to write
169 &cbWritten, // number of bytes written
170 NULL); // not overlapped I/O
171
172 if (!fSuccess || cbReplyBytes != cbWritten)
173 {
174 _tprintf(TEXT("InstanceThread WriteFile failed, GLE=%d.\n"), GetLastError());
175 break;
176 }
177 }
178
179 // Flush the pipe to allow the client to read the pipe‘s contents
180 // before disconnecting. Then disconnect the pipe, and close the
181 // handle to this pipe instance.
182
183 FlushFileBuffers(hPipe);
184 DisconnectNamedPipe(hPipe);
185 CloseHandle(hPipe);
186
187 HeapFree(hHeap, 0, pchRequest);
188 HeapFree(hHeap, 0, pchReply);
189
190 printf("InstanceThread exitting.\n");
191 return 1;
192 }
193
194 VOID GetAnswerToRequest( LPTSTR pchRequest,
195 LPTSTR pchReply,
196 LPDWORD pchBytes )
197 // This routine is a simple function to print the client request to the console
198 // and populate the reply buffer with a default data string. This is where you
199 // would put the actual client request processing code that runs in the context
200 // of an instance thread. Keep in mind the main thread will continue to wait for
201 // and receive other client connections while the instance thread is working.
202 {
203 _tprintf( TEXT("Client Request String:\"%S\"\n"), pchRequest );//这里注意大小写的%S,见上一篇随笔
204
205 // Check the outgoing message to make sure it‘s not too long for the buffer.
206 if (FAILED(StringCchCopy( pchReply, BUFSIZE, TEXT("default answer from server") )))
207 {
208 *pchBytes = 0;
209 pchReply[0] = 0;
210 printf("StringCchCopy failed, no outgoing message.\n");
211 return;
212 }
213 *pchBytes = (lstrlen(pchReply)+1)*sizeof(TCHAR);
214 }
客户端:
// client.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>#define BUFSIZE 512
int _tmain(int argc, TCHAR *argv[])
{
HANDLE hPipe;
LPTSTR lpvMessage=TEXT("Default message from client.");
TCHAR chBuf[BUFSIZE];
BOOL fSuccess = FALSE;
DWORD cbRead, cbToWrite, cbWritten, dwMode;
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");if( argc > 1 )
lpvMessage = argv[1];// Try to open a named pipe; wait for it, if necessary.
while (1)
{
hPipe = CreateFile(
lpszPipename, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file// Break if the pipe handle is valid.
if (hPipe != INVALID_HANDLE_VALUE)
break;// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (GetLastError() != ERROR_PIPE_BUSY)
{
_tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() );
return -1;
}// All pipe instances are busy, so wait for 20 seconds.
if ( ! WaitNamedPipe(lpszPipename, 20000))
{
printf("Could not open pipe: 20 second wait timed out.");
return -1;
}
}// The pipe connected; change to message-read mode.
dwMode = PIPE_READMODE_MESSAGE;
fSuccess = SetNamedPipeHandleState(
hPipe, // pipe handle
&dwMode, // new pipe mode
NULL, // don‘t set maximum bytes
NULL); // don‘t set maximum time
if ( ! fSuccess)
{
_tprintf( TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError() );
return -1;
}// Send a message to the pipe server.
cbToWrite = (lstrlen(lpvMessage)+1)*sizeof(TCHAR);
_tprintf( TEXT("Sending %d byte message: \"%s\"\n"), cbToWrite, lpvMessage);fSuccess = WriteFile(
hPipe, // pipe handle
lpvMessage, // message
cbToWrite, // message length
&cbWritten, // bytes written
NULL); // not overlappedif ( ! fSuccess)
{
_tprintf( TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError() );
return -1;
}printf("\nMessage sent to server, receiving reply as follows:\n");
do
{
// Read from the pipe.fSuccess = ReadFile(
hPipe, // pipe handle
chBuf, // buffer to receive reply
BUFSIZE*sizeof(TCHAR), // size of buffer
&cbRead, // number of bytes read
NULL); // not overlappedif ( ! fSuccess && GetLastError() != ERROR_MORE_DATA )
break;_tprintf( TEXT("\"%S\"\n"), chBuf );
} while ( ! fSuccess); // repeat loop if ERROR_MORE_DATAif ( ! fSuccess)
{
_tprintf( TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError() );
return -1;
}printf("\n<End of message, press ENTER to terminate connection and exit>");
_getch();CloseHandle(hPipe);
return 0;
}
命名管道-MSDN例子