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.
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 통신이 가능하게 만들어 주는 역할을 한다.
통해 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 ¶
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