E D R , A S I H C RSS

Named Pipe

1. def

MSDN

A named pipe is a named, one-way or duplex pipe for communication between the pipe server and one or more pipe clients. All instances of a
named pipe share the same pipe name, but each instance has its own buffers and handles, and provides a separate conduit for client-server communication. The use of instances enables multiple pipe clients to use the same named pipe simultaneously.

Any process can access named pipes, subject to security checks, making named pipes an easy form of communication between related or unrelated processes. Named pipes can be used to provide communication between processes on the same computer or between processes on different computers across a network.

Any process can act as both a server and a client, making peer-to-peer communication possible. As used here, the term pipe server refers to a process that creates a named pipe, and the term pipe client refers to a process that connects to an instance of a named pipe.

Pipe란 두 프로세스간의 통신을 위해 만들어진 것으로 Named Pipe는 말 그대로 이름이 있는 파이프라는 것이다. 이는 다른 컴퓨터와도 네트워크를
통해 Server / Client 통신이 가능하게 만들어 주는 역할을 한다.

2. using

Server
~cpp 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <windows.h> 
 
VOID InstanceThread(LPVOID); // 쓰레드 함수
VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD); // 스레드 
 
int xx = 0; 
 
DWORD main(VOID) 
{ 
   BOOL fConnected; 
   DWORD dwThreadId; 
   HANDLE hPipe, hThread; // 쓰레드 핸들
   LPTSTR lpszPipename = "\\.\pipe\mynamedpipe"; // 파이프 이름
 
// The main loop creates an instance of the named pipe and 
// then waits for a client to connect to it. When the client 
// connects, a thread is created to handle communications 
// with that client, and the loop is repeated. 
 
   for (;;) 
   { 
       // 쓰래드 함수를 생성한다.
      hPipe = CreateNamedPipe( 
          lpszPipename,             // pipe name 
          PIPE_ACCESS_DUPLEX,       // read/write access 
          PIPE_TYPE_MESSAGE |       // message type pipe 
          PIPE_READMODE_MESSAGE |   // message-read mode 
          PIPE_WAIT,                // blocking mode 
          PIPE_UNLIMITED_INSTANCES, // max. instances  
          BUFSIZE,                  // output buffer size 
          BUFSIZE,                  // input buffer size 
          PIPE_TIMEOUT,             // client time-out 
          NULL);                    // no security attribute 

      if (hPipe == INVALID_HANDLE_VALUE) 
          MyErrExit("CreatePipe"); 
 
      // Wait for the client to connect; if it succeeds, // 클라이언트를 연결을 기다린다.
      // the function returns a nonzero value. If the function returns // 접속이 될 경우 0 아닌 값이 리턴 되며 
      // zero, GetLastError returns ERROR_PIPE_CONNECTED. // 만약 0 값이 리턴이 될 경우 ERROR_PIPE_CONNECTED를 리턴한다.
 
      fConnected = ConnectNamedPipe(hPipe, NULL) ? 
         TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 
       // 연결이 되서 fConnected값이 TRUE가 되었으므로 
      if (fConnected) 
      { 
      // Create a thread for this client. // 연결된 클라이언트를 위한 쓰레드를 생성시킨다.
         hThread = CreateThread( 
            NULL,              // no security attribute 
            0,                 // default stack size 
            (LPTHREAD_START_ROUTINE) InstanceThread, // InstanceThread를 생성시킨다.
            (LPVOID) hPipe,    // thread parameter // 쓰레드 Parameter로 hPipe 핸들값이 들어간다.
            0,                 // not suspended 
            &dwThreadId);      // returns thread ID 
       // 쓰레드가 생성이 되면 hThread 값이 NULL 이고 그렇지 않으면 열어 놓은 Handle값을 닫아준다.
         if (hThread == NULL) 
            MyErrExit("CreateThread"); 
         else
            CloseHandle(hThread); 
 
      } 
      else 
        // The client could not connect, so close the pipe. 
         CloseHandle(hPipe); 
   } 
   return 1; 
} 
 
VOID InstanceThread(LPVOID lpvParam) 
{ 
   CHAR chRequest[BUFSIZE]; // 수신 버퍼
   CHAR chReply[BUFSIZE]; //  송신 버퍼
   DWORD cbBytesRead, cbReplyBytes, cbWritten; 
   BOOL fSuccess; 
   HANDLE hPipe; 
 
// The thread's parameter is a handle to a pipe instance. 
 
   hPipe = (HANDLE) lpvParam; 
 
   while (1) 
   { 
   // Read client requests from the pipe. 
   // hPipe 핸들에서 chRequst에 BUFSIZE만큼 읽어 들여온다.
      fSuccess = ReadFile( 
         hPipe,        // handle to pipe 
         chRequest,    // buffer to receive data 
         BUFSIZE,      // size of buffer 
         &cbBytesRead, // number of bytes read 
         NULL);        // not overlapped I/O 

      if (! fSuccess || cbBytesRead == 0) 
         break; 
   // Request 에 대한 대답을 chReply 버퍼에 넣어준다.
      GetAnswerToRequest(chRequest, chReply, &cbReplyBytes); 
   // chReply를 대답한다.
   // Write the reply to the pipe. 
      fSuccess = WriteFile( 
         hPipe,        // handle to pipe 
         chReply,      // buffer to write from 
         cbReplyBytes, // number of bytes to write 
         &cbWritten,   // number of bytes written 
         NULL);        // not overlapped I/O 

      if (! fSuccess || cbReplyBytes != cbWritten) break; 
  } 
 
// Flush the pipe to allow the client to read the pipe's contents 
// before disconnecting. Then disconnect the pipe, and close the 
// handle to this pipe instance. 
// 버퍼의 남은 Data를 Flush 해준다.
   FlushFileBuffers(hPipe); 
   DisconnectNamedPipe(hPipe); 
   CloseHandle(hPipe); 
} 
Client
~cpp 
#include <windows.h> 
 
DWORD main(int argc, char *argv[]) 
{ 
   HANDLE hPipe; 
   LPVOID lpvMessage; 
   CHAR chBuf[512]; 
   BOOL fSuccess; 
   DWORD cbRead, cbWritten, dwMode; 
   LPTSTR lpszPipename = "\\.\pipe\mynamedpipe"; 
 
// 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,           // no 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) 
         MyErrExit("Could not open pipe"); 
 
      // All pipe instances are busy, so wait for 20 seconds. 
 
      if (! WaitNamedPipe(lpszPipename, 20000) ) 
         MyErrExit("Could not open pipe"); 
   } // 파일을 열고 Pipe를 서버에 접속하기 전까지 대기 상태로 만들어둔다.
 
// The pipe connected; change to message-read mode. 
// 파이프가 연결이 되면 파이프를 읽기용으로 바꾼다.
// 여기서 잠깐 PIPE_READMODE_MESSAGE는 읽기용이라고 나와있지만 MSDN에는 이 모드가 새로운 모드로
// 읽기와 쓰기 모두 가능한 모드라고 나와 있다. 
// Default는 PIPE_READMODE_DATA 이고 PIPE_READMODE_MESSAGE가 실패할 경우 default로 정해진다.
   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) 
      MyErrExit("SetNamedPipeHandleState"); 
 
// Send a message to the pipe server. 
// 파이프로 메세지를 보낸다. 
   lpvMessage = (argc > 1) ? argv[1] : "default message"; 
 
   fSuccess = WriteFile( 
      hPipe,                  // pipe handle 
      lpvMessage,             // message 
      strlen(lpvMessage) + 1, // message length 
      &cbWritten,             // bytes written 
      NULL);                  // not overlapped 
   if (! fSuccess) 
      MyErrExit("WriteFile"); 
// 파이프로 부터 메세지를 읽어온다.
   do 
   { 
   // Read from the pipe. 
   // 파이프로부터 읽기
      fSuccess = ReadFile( 
         hPipe,    // pipe handle 
         chBuf,    // buffer to receive reply 
         512,      // size of buffer 
         &cbRead,  // number of bytes read 
         NULL);    // not overlapped 
 
      if (! fSuccess && GetLastError() != ERROR_MORE_DATA) 
         break; 
 
      // Reply from the pipe is written to STDOUT. 
      // STDOUT로 Reply 쓰기
      if (! WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), 
         chBuf, cbRead, &cbWritten, NULL)) 
      {
         break; 
      }
 
   } while (! fSuccess);  // repeat loop if ERROR_MORE_DATA 
 
   CloseHandle(hPipe); 
 
   return 0; 
} 

3. example

실제 예제 파일 NamedPipe를 이용한 Chat Program http://www.zeropage.org/pds/20031103027/NamedPipe.zip

4. function

~cpp CallNamedPipe 메세지 형식의 Named Pipe를 Connect할 때 쓰이는 함수
~cpp ConnectNamedPipe Named Pipe 에 Connect할 때 쓰이는 함수
~cpp CreateNamedPipe Named Pipe를 생성한다.
~cpp CreatePipe anonymous Pipe를 생성한다.
~cpp DisconnectNamedPipe Named Pipe Server에 연결을 끊는다.
~cpp GetNamedPipeHandleState 특정 Named Pipe에 대한 정보를 얻는다.
~cpp GetNamedPipeInfo 특정 Named Pipe에 대한 정보를 얻는다.
~cpp PeekNamedPipe anonymous / Named Pipe로부터 Data를 얻어온다.
~cpp SetNamedPipeHandleState ~cpp NamedPipe~cpp ReadMode , ~cpp Block 상태를 Set한다.
~cpp TransactNamedPipe Single Operation으로 Read & Write를 할 수 있는 function 이다.
~cpp WaitNamedPipe Connection 상태에서 Time-Out OR 정해준 시간이 되기 전까지 Wait한다.

contributor fnwinter

어분류,도구분류
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:50
Processing time 0.0478 sec