Transaksi pada Pipa Bernama

Transaksi pipa bernama adalah komunikasi klien/server yang menggabungkan operasi tulis dan operasi baca ke dalam satu operasi jaringan. Transaksi hanya dapat digunakan pada dupleks, pipa jenis pesan. Transaksi meningkatkan performa komunikasi jaringan antara klien dan server jarak jauh. Proses dapat menggunakan fungsi TransactNamedPipe dan CallNamedPipe untuk melakukan transaksi pipa bernama.

Fungsi TransactNamedPipe paling sering digunakan oleh klien pipa untuk menulis pesan permintaan ke server pipa bernama dan membaca pesan respons server. Klien pipa harus menentukan GENERIC_READ | GENERIC_WRITE akses saat membuka handel pipanya dengan memanggil fungsi CreateFile . Kemudian, klien pipa mengatur handel pipa ke mode baca pesan dengan memanggil fungsi SetNamedPipeHandleState . Jika buffer baca yang ditentukan dalam panggilan ke TransactNamedPipe tidak cukup besar untuk menahan seluruh pesan yang ditulis oleh server, fungsi mengembalikan nol dan GetLastError mengembalikan ERROR_MORE_DATA. Klien dapat membaca sisa pesan dengan memanggil fungsi ReadFile, ReadFileEx, atau PeekNamedPipe .

TransactNamedPipe biasanya dipanggil oleh klien pipa, tetapi juga dapat digunakan oleh server pipa.

Contoh berikut menunjukkan klien pipa menggunakan TransactNamedPipe. Klien pipa ini dapat digunakan dengan salah satu server pipa yang tercantum di bawah Lihat Juga.

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

Klien pipa menggunakan CallNamedPipe untuk menggabungkan panggilan fungsi CreateFile, WaitNamedPipe (jika perlu), TransactNamedPipe, dan CloseHandle ke dalam satu panggilan. Karena handel pipa ditutup sebelum fungsi kembali, byte tambahan apa pun dalam pesan hilang jika pesan lebih besar dari ukuran buffer baca yang ditentukan. Contoh berikut adalah contoh sebelumnya yang ditulis ulang untuk menggunakan CallNamedPipe.

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

Server pipa multithreaded

Server pipa bernama menggunakan I/O yang tumpang tindih

Server pipa bernama menggunakan rutinitas penyelesaian