首页 > 代码库 > 命名管道-MSDN例子

命名管道-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, 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 overlapped 

   if ( ! 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 overlapped 
 
      if ( ! fSuccess && GetLastError() != ERROR_MORE_DATA )
         break; 
 
      _tprintf( TEXT("\"%S\"\n"), chBuf ); 
   } while ( ! fSuccess);  // repeat loop if ERROR_MORE_DATA 

   if ( ! 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; 
}