명명된 파이프 클라이언트

명명된 파이프 클라이언트는 CreateFile 함수를 사용하여 명명된 파이프에 대한 핸들을 엽니다. 파이프가 있지만 모든 인스턴스가 사용 중인 경우 CreateFileINVALID_HANDLE_VALUE 반환하고 GetLastError 함수는 ERROR_PIPE_BUSY 반환합니다. 이 경우 명명된 파이프 클라이언트는 WaitNamedPipe 함수를 사용하여 명명된 파이프의 instance 사용할 수 있을 때까지 기다립니다.

서버가 파이프를 만들 때 지정된 액세스(이중, 아웃바운드 또는 인바운드)와 호환되지 않는 경우 CreateFile 함수가 실패합니다. 이중 파이프의 경우 클라이언트는 읽기, 쓰기 또는 읽기/쓰기 액세스를 지정할 수 있습니다. 아웃바운드 파이프(쓰기 전용 서버)의 경우 클라이언트는 읽기 전용 액세스를 지정해야 합니다. 인바운드 파이프(읽기 전용 서버)의 경우 클라이언트는 쓰기 전용 액세스를 지정해야 합니다.

CreateFile에서 반환된 핸들은 기본적으로 바이트 읽기 모드, 차단 대기 모드, 겹치는 모드 사용 안 함 및 쓰기 모드 사용 안 함으로 설정됩니다. 파이프 클라이언트는 CreateFile 을 사용하여 FILE_FLAG_OVERLAPPED 지정하여 겹치는 모드를 사용하도록 설정하거나 FILE_FLAG_WRITE_THROUGH 지정하여 쓰기 모드를 사용하도록 설정할 수 있습니다. 클라이언트는 SetNamedPipeHandleState 함수를 사용하여 PIPE_NOWAIT 지정하여 비블로킹 모드를 사용하도록 설정하거나 PIPE_READMODE_MESSAGE 지정하여 메시지 읽기 모드를 사용하도록 설정할 수 있습니다.

다음 예제에서는 명명된 파이프를 열고, 파이프 핸들을 메시지 읽기 모드로 설정하고, WriteFile 함수를 사용하여 서버에 요청을 보내고, ReadFile 함수를 사용하여 서버의 회신을 읽는 파이프 클라이언트를 보여 줍니다. 이 파이프 클라이언트는 이 항목의 맨 아래에 나열된 메시지 유형 서버와 함께 사용할 수 있습니다. 그러나 바이트 형식 서버를 사용하면 SetNamedPipeHandleState 를 호출하여 메시지 읽기 모드로 변경하면 이 파이프 클라이언트가 실패합니다. 클라이언트가 메시지 읽기 모드에서 파이프에서 읽고 있으므로 부분 메시지를 읽은 후 ReadFile 작업이 0을 반환할 수 있습니다. 이는 메시지가 읽기 버퍼보다 큰 경우에 발생합니다. 이 경우 GetLastError 는 ERROR_MORE_DATA 반환하고 클라이언트는 ReadFile에 대한 추가 호출을 사용하여 메시지의 나머지 부분을 읽을 수 있습니다.

이 파이프 클라이언트는 참고 항목 아래에 나열된 파이프 서버와 함께 사용할 수 있습니다.

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

다중 스레드 파이프 서버

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

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