Share via


명명된 파이프의 트랜잭션

명명된 파이프 트랜잭션은 쓰기 작업과 읽기 작업을 단일 네트워크 작업으로 결합하는 클라이언트/서버 통신입니다. 트랜잭션은 이중 메시지 형식 파이프에서만 사용할 수 있습니다. 트랜잭션은 클라이언트와 원격 서버 간의 네트워크 통신 성능을 향상시킵니다. 프로세스는 TransactNamedPipeCallNamedPipe 함수를 사용하여 명명된 파이프 트랜잭션을 수행할 수 있습니다.

TransactNamedPipe 함수는 파이프 클라이언트가 명명된 파이프 서버에 요청 메시지를 작성하고 서버의 응답 메시지를 읽는 데 가장 일반적으로 사용됩니다. 파이프 클라이언트는 GENERIC_READ 지정해야 합니다. | CreateFile 함수를 호출하여 파이프 핸들을 열 때 액세스를 GENERIC_WRITE. 그런 다음 파이프 클라이언트는 SetNamedPipeHandleState 함수를 호출하여 파이프 핸들을 메시지 읽기 모드로 설정합니다. TransactNamedPipe 호출에 지정된 읽기 버퍼가 서버에서 작성한 전체 메시지를 저장할 만큼 크지 않으면 함수는 0을 반환하고 GetLastError는 ERROR_MORE_DATA 반환합니다. 클라이언트는 ReadFile, ReadFileEx 또는 PeekNamedPipe 함수를 호출하여 메시지의 나머지 부분을 읽을 수 있습니다.

TransactNamedPipe 는 일반적으로 파이프 클라이언트에서 호출되지만 파이프 서버에서도 사용할 수 있습니다.

다음 예제에서는 TransactNamedPipe를 사용하는 파이프 클라이언트를 보여줍니다. 이 파이프 클라이언트는 참고 항목 아래에 나열된 파이프 서버와 함께 사용할 수 있습니다.

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

파이프 클라이언트는 CallNamedPipe 를 사용하여 CreateFile, WaitNamedPipe (필요한 경우), TransactNamedPipeCloseHandle 함수 호출을 단일 호출로 결합합니다. 함수가 반환되기 전에 파이프 핸들이 닫혀 있으므로 메시지가 읽기 버퍼의 지정된 크기보다 크면 메시지의 추가 바이트가 손실됩니다. 다음 예제는 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; 
}

다중 스레드 파이프 서버

겹치는 I/O를 사용하는 명명된 파이프 서버

완료 루틴을 사용하는 명명된 파이프 서버