Pipe는 두 프로세스를 잇는 통로입니다.


예를 들어, 두 개의 수조가 있고 그 사이를 파이프로 관통해 연결한다고 합시다.

그럼 하나의 수조에 물을 채운다면 그 물이 파이프를 따라 흘러 또 다른 수조로 들어가게 되겠죠?


이처럼, 프로세스 간에도 Pipe를 연결한다면 원하는 정보를 다른 프로세스로 전달할 수 있습니다.


Pipe에는 Named PipeAnonymous 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;

}




'Programming Language > C/C++' 카테고리의 다른 글

C++ 기본 자료형  (0) 2016.05.06
StrSafe 함수들  (0) 2015.09.19
C 데이터, 스택, 힙 영역  (0) 2014.12.08
C++ Volatile 키워드  (0) 2014.11.15
C++ 포인터와 레퍼런스의 차이  (0) 2014.11.12
Posted by 긍정왕오킹