네임드 파이프 예제
Pipe는 두 프로세스를 잇는 통로입니다.
예를 들어, 두 개의 수조가 있고 그 사이를 파이프로 관통해 연결한다고 합시다.
그럼 하나의 수조에 물을 채운다면 그 물이 파이프를 따라 흘러 또 다른 수조로 들어가게 되겠죠?
이처럼, 프로세스 간에도 Pipe를 연결한다면 원하는 정보를 다른 프로세스로 전달할 수 있습니다.
Pipe에는 Named Pipe와 Anonymous Pipe, 두 종류가 존재하는데요.
간략하게 설명하면
Anonymous Pipe : 이름없는 파이프, 한쪽 방향으로만 데이터 전송, 부모 => 자식 프로세스
Named Pipe : 이름있는 파이프, 양쪽 방향으로 데이터 전송, 프로세스 <=> 프로세스
아래는 Named Pipe를 이용해 프로세스간 통신을 하는 코드입니다.
- 출처 : http://ezbeat.tistory.com/300
서버 코드
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#define PIPE_NAME "\\\\.\\pipe\\test_pipe" // 파이프 이름 설정, 이 파이프로 통신을 할 것임
int ConnectClient(HANDLE hNamePipe)
{
TCHAR recvMessage[100];
TCHAR sendMessage[100];
DWORD recvSize;
DWORD sendSize;
while(1)
{
_tprintf(_T("Input Send Message : "));
_tscanf(_T("%s"),sendMessage);
//sendSize -> NULL 포함한 바이트 수
if(!(WriteFile(
hNamePipe,
sendMessage,
(_tcslen(sendMessage)+1)*sizeof(TCHAR),
&sendSize,
NULL
))) //
{
_tprintf(_T("WriteFile error! \n"));
return -1;
}
FlushFileBuffers(hNamePipe);
//recvSize -> NULL 포함한 바이트 수
if(!(ReadFile(
hNamePipe,
recvMessage,
sizeof(recvMessage)-sizeof(TCHAR)*1,
&recvSize,
NULL
)))
{
printf("ReadFile error! \n");
return -1;
}
recvMessage[recvSize/sizeof(TCHAR)-1] = _T('\x00');
_tprintf(_T("Recv Message : %s \n"),recvMessage);
}
return 1;
}
int _tmain(int argc,TCHAR* argv[])
{
HANDLE hNamePipe;
TCHAR pipe_name[] = _T(PIPE_NAME); // #define 한 파이프 이름
_tprintf(_T("==== Server ==== \n"));
//NamedPipe 생성
hNamePipe = CreateNamedPipe(
pipe_name,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0,
0,
20000, // 대기 Timeout 시간
NULL
);
if(hNamePipe == INVALID_HANDLE_VALUE)
{
printf("CreateNamePipe error! \n");
return -1;
}
while(1)
{
//생성한 Named Pipe의 핸들을 누군가 얻어갈 때까지 대기..
if(!(ConnectNamedPipe(hNamePipe,NULL)))
{
CloseHandle(hNamePipe);
return -1;
}
else
{
if(ConnectClient(hNamePipe) == -1)
break;
}
}
DisconnectNamedPipe(hNamePipe);
CloseHandle(hNamePipe);
_tprintf(_T("Program exit! \n"));
return 1;
}
클라이언트 코드
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <tchar.h>
#define PIPE_NAME "\\\\.\\pipe\\test_pipe" // 서버의 파이프 이름과 동일한 파이프 사용
int ConnectServer(HANDLE hNamePipe)
{
TCHAR recvMessage[100];
TCHAR sendMessage[100];
DWORD recvSize;
DWORD sendSize;
while(1)
{
if(!(ReadFile(
hNamePipe,
recvMessage,
sizeof(recvMessage)-sizeof(TCHAR)*1,
&recvSize,
NULL
)))
{
_tprintf(_T("ReadFile error! \n"));
return -1;
}
recvMessage[recvSize/sizeof(TCHAR)-1] = _T('\x00');
_tprintf(_T("Recv Message : %s \n"),recvMessage);
_tprintf(_T("Input Send Message : "));
_tscanf(_T("%s"),sendMessage);
if(!(WriteFile(
hNamePipe,
sendMessage,
(_tcslen(sendMessage)+1)*sizeof(TCHAR),
&sendSize,
NULL
)))
{
_tprintf(_T("WriteFile error! \n"));
return -1;
}
FlushFileBuffers(hNamePipe);
}
return 1;
}
int _tmain(int argc, TCHAR* argv[])
{
TCHAR pipe_name[] = _T(PIPE_NAME);
HANDLE hNamePipe;
_tprintf(_T("==== Client ==== \n"));
while(1)
{
// 파이프 이름으로 핸들 열기
hNamePipe = CreateFile(pipe_name,GENERIC_READ | GENERIC_WRITE, 0,NULL,OPEN_EXISTING,0,NULL);
if(hNamePipe == INVALID_HANDLE_VALUE)
{
_tprintf(_T("CreateFile error! \n"));
return -1;
}
DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
if(!(SetNamedPipeHandleState(hNamePipe,&pipeMode,NULL,NULL)))
{
_tprintf(_T("SetNamedPipeHandleState error! \n"));
CloseHandle(hNamePipe);
return -1;
}
else
{
if(ConnectServer(hNamePipe) == -1)
break;
}
}
CloseHandle(hNamePipe);
return 0;
}