Named Pipe-Client

Ein Named Pipe-Client verwendet die CreateFile-Funktion , um ein Handle für eine benannte Pipe zu öffnen. Wenn die Pipe vorhanden ist, aber alle Instanzen ausgelastet sind, gibt CreateFileINVALID_HANDLE_VALUE zurück, und die GetLastError-Funktion gibt ERROR_PIPE_BUSY zurück. In diesem Fall wird vom Named Pipe-Client die WaitNamedPipe-Funktion verwendet, um zu warten, bis eine instance der benannten Pipe verfügbar wird.

Die CreateFile-Funktion schlägt fehl, wenn der angegebene Zugriff mit dem angegebenen Zugriff (Duplex, ausgehend oder eingehender Zugriff) nicht kompatibel ist, wenn der Server die Pipe erstellt hat. Bei einer Duplexpipe kann der Client Lese-, Schreib- oder Lese-/Schreibzugriff angeben. Für eine ausgehende Pipe (schreibgeschützter Server) muss der Client schreibgeschützten Zugriff angeben. und für eine eingehende Pipe (schreibgeschützter Server) muss der Client schreibgeschützten Zugriff angeben.

Das von CreateFile zurückgegebene Handle weist standardmäßig den Byte-Lesemodus, den Blockierungs-Wartemodus, den überlappenden Modus deaktiviert und den Schreibmodus deaktiviert auf. Der Pipeclient kann CreateFile verwenden, um den Überlappungsmodus zu aktivieren, indem FILE_FLAG_OVERLAPPED angegeben wird, oder um den Schreibmodus durch Angabe FILE_FLAG_WRITE_THROUGH zu aktivieren. Der Client kann die SetNamedPipeHandleState-Funktion verwenden, um den Nichtblockierungsmodus zu aktivieren, indem PIPE_NOWAIT angegeben wird, oder um den Nachrichtenlesemodus durch Angabe von PIPE_READMODE_MESSAGE zu aktivieren.

Das folgende Beispiel zeigt einen Pipeclient, der eine benannte Pipe öffnet, das Pipehandle auf den Nachrichtenlesemodus festlegt, die WriteFile-Funktion verwendet, um eine Anforderung an den Server zu senden, und die ReadFile-Funktion zum Lesen der Antwort des Servers verwendet. Dieser Pipeclient kann mit jedem der nachrichtentypbasierten Server verwendet werden, die unten in diesem Thema aufgeführt sind. Bei einem Bytetypserver schlägt dieser Pipeclient jedoch fehl, wenn er SetNamedPipeHandleState aufruft, um in den Nachrichtenlesemodus zu wechseln. Da der Client im Nachrichtenlesemodus aus der Pipe liest, ist es möglich, dass der ReadFile-Vorgang nach dem Lesen einer Teilnachricht null zurückgibt. Dies geschieht, wenn die Nachricht größer als der Lesepuffer ist. In dieser Situation gibt GetLastError ERROR_MORE_DATA zurück, und der Client kann den Rest der Nachricht mithilfe zusätzlicher Aufrufe von ReadFile lesen.

Dieser Pipeclient kann mit jedem der unter Siehe auch aufgeführten Pipeserver verwendet werden.

#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; 
}

Multithread-Pipeserver

Named Pipe-Server mit überlappenden E/A-Vorgängen

Named Pipe-Server mit Vervollständigungsroutinen