Freigeben über


Transaktionen auf Named Pipes

Eine benannte Pipetransaktion ist eine Client-/Serverkommunikation, die einen Schreibvorgang und einen Lesevorgang in einen einzelnen Netzwerkvorgang kombiniert. Eine Transaktion kann nur für eine Duplex-, Nachrichten-Typ-Pipe verwendet werden. Transaktionen verbessern die Leistung der Netzwerkkommunikation zwischen einem Client und einem Remoteserver. Prozesse können die TransactNamedPipe- und CallNamedPipe- Funktionen verwenden, um benannte Pipetransaktionen auszuführen.

Die TransactNamedPipe-Funktion wird am häufigsten von einem Pipeclient verwendet, um eine Anforderungsnachricht an den benannten Pipeserver zu schreiben und die Antwortnachricht des Servers zu lesen. Der Pipeclient muss GENERIC_READ | GENERIC_WRITE Zugriff beim Öffnen des Pipehandle durch Aufrufen der CreateFile--Funktion. Anschließend legt der Pipeclient den Pipehandle-Modus auf den Nachrichtenlesemodus fest, indem die funktion SetNamedPipeHandleState aufgerufen wird. Wenn der im Aufruf von TransactNamedPipe- angegebene Lesepuffer nicht groß genug ist, um die gesamte vom Server geschriebene Nachricht zu halten, gibt die Funktion Null zurück, und GetLastError- gibt ERROR_MORE_DATA zurück. Der Client kann den Rest der Nachricht lesen, indem entweder die funktion ReadFile, ReadFileExoder PeekNamedPipe-Funktion aufgerufen wird.

TransactNamedPipe wird in der Regel von Pipeclients aufgerufen, kann aber auch von einem Pipeserver verwendet werden.

Das folgende Beispiel zeigt einen Pipeclient mit TransactNamedPipe. Dieser Pipeclient kann mit einem 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 lpszWrite = TEXT("Default message from client"); 
   TCHAR chReadBuf[BUFSIZE]; 
   BOOL fSuccess; 
   DWORD cbRead, dwMode; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 

   if( argc > 1)
   {
      lpszWrite = 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) 
      {
         printf("Could not open pipe\n"); 
         return 0;
      }
 
      // All pipe instances are busy, so wait for 20 seconds. 
      if (! WaitNamedPipe(lpszPipename, 20000) ) 
      {
         printf("Could not open pipe\n"); 
         return 0;
      }
  } 
 
   // 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) 
   {
      printf("SetNamedPipeHandleState failed.\n"); 
      return 0;
   }
 
   // Send a message to the pipe server and read the response. 
   fSuccess = TransactNamedPipe( 
      hPipe,                  // pipe handle 
      lpszWrite,              // message to server
      (lstrlen(lpszWrite)+1)*sizeof(TCHAR), // message length 
      chReadBuf,              // buffer to receive reply
      BUFSIZE*sizeof(TCHAR),  // size of read buffer
      &cbRead,                // bytes read
      NULL);                  // not overlapped 

   if (!fSuccess && (GetLastError() != ERROR_MORE_DATA)) 
   {
      printf("TransactNamedPipe failed.\n"); 
      return 0;
   }
 
   while(1)
   { 
      _tprintf(TEXT("%s\n"), chReadBuf);

      // Break if TransactNamedPipe or ReadFile is successful
      if(fSuccess)
         break;

      // Read from the pipe if there is more data in the message.
      fSuccess = ReadFile( 
         hPipe,      // pipe handle 
         chReadBuf,  // buffer to receive reply 
         BUFSIZE*sizeof(TCHAR),  // size of buffer 
         &cbRead,  // number of bytes read 
         NULL);    // not overlapped 

      // Exit if an error other than ERROR_MORE_DATA occurs.
      if( !fSuccess && (GetLastError() != ERROR_MORE_DATA)) 
         break;
      else _tprintf( TEXT("%s\n"), chReadBuf); 
   }

   _getch(); 

   CloseHandle(hPipe); 
 
   return 0; 
}

Ein Pipeclient verwendet CallNamedPipe-, um die CreateFile-, WaitNamedPipe- (falls erforderlich), TransactNamedPipe-und CloseHandle Funktionsaufrufe in einen einzelnen Aufruf zu kombinieren. Da das Pipehandle vor dem Zurückgeben der Funktion geschlossen wird, gehen alle zusätzlichen Bytes in der Nachricht verloren, wenn die Nachricht größer als die angegebene Größe des Lesepuffers ist. Das folgende Beispiel ist das vorherige Beispiel, um CallNamedPipezu verwenden.

#include <windows.h> 
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

#define BUFSIZE 512
 
int _tmain(int argc, TCHAR *argv[]) 
{ 
   LPTSTR lpszWrite = TEXT("Default message from client"); 
   TCHAR chReadBuf[BUFSIZE]; 
   BOOL fSuccess; 
   DWORD cbRead; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 

   if( argc > 1)
   {
      lpszWrite = argv[1]; 
   }
 
   fSuccess = CallNamedPipe( 
      lpszPipename,        // pipe name 
      lpszWrite,           // message to server 
      (lstrlen(lpszWrite)+1)*sizeof(TCHAR), // message length 
      chReadBuf,              // buffer to receive reply 
      BUFSIZE*sizeof(TCHAR),  // size of read buffer 
      &cbRead,                // number of bytes read 
      20000);                 // waits for 20 seconds 
 
   if (fSuccess || GetLastError() == ERROR_MORE_DATA) 
   { 
      _tprintf( TEXT("%s\n"), chReadBuf ); 
    
      // The pipe is closed; no more data can be read. 
 
      if (! fSuccess) 
      {
         printf("\nExtra data in message was lost\n"); 
      }
   }
 
   _getch(); 

   return 0; 
}

multithreaded pipe server

benannten Pipeserver mit überlappender E/A-

named pipe server using completion routines