IPC별 특성 


 

메일슬롯 

이름없는파이프 

이름있는파이프 

방향성 

단방향 ,브로드캐스팅

단방향 

양방향 

통신범위 

제한 없음 

부모 자식 프로세스 

제한 없음 





예제8-1


이름없는 파이프


#include <windows.h>

#include <tchar.h>

#include <stdio.h>


int _tmain(int argc, LPTSTR argv[])

{

HANDLE hReadPipe, hWritePipe; //pipe handle


TCHAR sendString[] = _T("anonymous pipe");

TCHAR recvString[100];


DWORD bytesWritten;

DWORD bytesRead;          


/* pipe 생성 */

CreatePipe(&hReadPipe, &hWritePipe, NULL, 0);

/* 이름없는 파이프는 단방향성이기에 함수를 호출하면 파이프의 쓰는 부분과 읽는 부분을 반환받는다. */


/* pipe의 한쪽 끝을 이용한 데이터 송신 */ 

WriteFile(hWritePipe, sendString, lstrlen(sendString)*sizeof(TCHAR), &bytesWritten,

                                                                                                                     NULL);

_tprintf( _T("string send: %s \n"), sendString);



/* pipe의 다른 한쪽 끝을 이용한 데이터 수신 */ 

ReadFile(hReadPipe, recvString, bytesWritten, &bytesRead, NULL);

recvString[bytesRead/sizeof(TCHAR)] = 0;

_tprintf( _T("string recv: %s \n"), recvString);



CloseHandle(hReadPipe);

CloseHandle(hWritePipe);


return 0;

}


예제를 보면 CreatePipe함수를 호출하는 프로세스가 파이프의 읽고 쓰는 핸들을 모두 가지고 있다. 

이름없는 파이프는 부모 자식 프로세스간 에만  통신이 가능하다고 위에 나왔다.

 부모 프로세스는 자식 프로세스에 핸들을 상속 할 수 있기에 자식프로세스에 핸들을 상속하여  통신이 가능하다.




이름있는 파이프 프로그래밍 모델





1. CreateNamedPipe 함수에 의해 생성

2. ConnectNamedPipe 함수에 의해 연결 대기 상태로 전환

3. Client의 CreateFile 함수 호출에 의한 파이프 오픈


이름 있는 파이프는 양방향 통신이다.

먼저 서버가 파이프를 생성 한다.

CreateNamePipe함수를 호출하면 서버는 파이프를 가지고 있는다. 하지만 말그대로 가지고만 있을 뿐 외부와의 연결은 되지않는 상태이다.

외부와의 연결을 위해

ConnectNamePipe 함수를 호출통하여 외부에 파이프를 노출시킨다.

외부에서 파이프에 연결은 CreateFile 함수를 이용한다.




예제 8-2

이름있는파이프 서버


#include <stdio.h>

#include <stdlib.h>

#include <windows.h> 


#define BUF_SIZE 1024


int CommToClient(HANDLE);


int _tmain(int argc, TCHAR* argv[]) 

{

LPTSTR pipeName = _T("\\\\.\\pipe\\simple_pipe"); 


HANDLE hPipe;

while(1)

{

  hPipe = CreateNamedPipe ( 

  pipeName,            // 파이프 이름

  PIPE_ACCESS_DUPLEX,       // 읽기,쓰기 모드 지정

  PIPE_TYPE_MESSAGE |

  PIPE_READMODE_MESSAGE | PIPE_WAIT,

  PIPE_UNLIMITED_INSTANCES, // 최대 인스턴스 개수.

  BUF_SIZE,                  // 출력버퍼 사이즈.

  BUF_SIZE,                  // 입력버퍼 사이즈 

  20000,                   // 클라이언트 타임-아웃  

  NULL                    // 디폴트 보안 속성

  );

  

  if (hPipe == INVALID_HANDLE_VALUE) 

  {

  _tprintf( _T("CreatePipe failed")); 

  return -1;

  }

  

  BOOL isSuccess; 

  isSuccess = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 

  

  if (isSuccess) 

  CommToClient(hPipe);

  else 

  CloseHandle(hPipe); 

}

return 1; 


int CommToClient(HANDLE hPipe)

TCHAR fileName[MAX_PATH];

TCHAR dataBuf[BUF_SIZE];


BOOL isSuccess;

DWORD fileNameSize;


isSuccess = ReadFile ( 

hPipe,        // 파이프 핸들 

fileName,    // read 버퍼 지정.

MAX_PATH * sizeof(TCHAR), // read 버퍼 사이즈 

&fileNameSize,  // 수신한 데이터 크기

NULL);       


if (!isSuccess || fileNameSize == 0) 

{

_tprintf( _T("Pipe read message error! \n") );

return -1; 

}


FILE * filePtr = _tfopen(fileName, _T("r") );


if(filePtr == NULL)

{

_tprintf( _T("File open fault! \n") );

return -1; 

}


DWORD bytesWritten = 0;

DWORD bytesRead = 0;


while( !feof(filePtr) )

{

bytesRead = fread(dataBuf, 1, BUF_SIZE, filePtr);


WriteFile ( 

hPipe, // 파이프 핸들

dataBuf, // 전송할 데이터 버퍼  

bytesRead, // 전송할 데이터 크기 

&bytesWritten, // 전송된 데이터 크기 

NULL);


       if (bytesRead != bytesWritten)

{

   _tprintf( _T("Pipe write message error! \n") );

   break; 

}

}


FlushFileBuffers(hPipe); 

DisconnectNamedPipe(hPipe); 

CloseHandle(hPipe); 

return 1;

}




예제 8-3

이름있는 파이프 클라이언트



#include <stdio.h>

#include <stdlib.h>

#include <windows.h>


#define BUF_SIZE 1024


int _tmain(int argc, TCHAR *argv[]) 

{

    HANDLE hPipe;

    TCHAR readDataBuf[BUF_SIZE + 1];

    LPTSTR pipeName = _T("\\\\.\\pipe\\simple_pipe"); 

    

    while(1)

    {

      hPipe = CreateFile( 

      pipeName,             // 파이프 이름 

      GENERIC_READ | GENERIC_WRITE, // 읽기, 쓰기 모드 동                         

                                                                                                               시 지정 

      0,

      NULL,

      OPEN_EXISTING,

      0,

      NULL

      );

     

      if (hPipe != INVALID_HANDLE_VALUE)

         break;

         

      if (GetLastError() != ERROR_PIPE_BUSY)

      {

         _tprintf( _T("Could not open pipe \n") );        

         return 0;

      }

     

      if (!WaitNamedPipe(pipeName, 20000))

      {

         _tprintf( _T("Could not open pipe \n") );

         return 0;

      }

    }

    

    DWORD pipeMode = PIPE_READMODE_MESSAGE|PIPE_WAIT; // 메시지 기반으로 모드 변경.

    BOOL isSuccess = SetNamedPipeHandleState (

                       hPipe,      // 파이프 핸들

                       &pipeMode,  // 변경할 모드 정보.  

                       NULL,     // 설정하지 않는다. 

                       NULL);    // 설정하지 않는다. 

    

    if (!isSuccess)

    {

        _tprintf( _T("SetNamedPipeHandleState failed") ); 

        return 0;

    }

    

    LPCTSTR fileName = _T("news.txt");

    DWORD bytesWritten = 0;

    

    isSuccess = WriteFile (

                    hPipe,                // 파이프 핸들

                    fileName,             // 전송할 메시지 

                    (lstrlen(fileName)+1) * sizeof(TCHAR), // 메시지 길이 

                    &bytesWritten,             // 전송된 바이트 수

                    NULL);

    

    if (!isSuccess) 

    {

      _tprintf( _T("WriteFile failed") ); 

      return 0;

    }

    

    DWORD bytesRead = 0;

    while(1) 

    {

        isSuccess = ReadFile(

                        hPipe, // 파이프 핸들

                        readDataBuf, // 데이터 수신할 버퍼

                        BUF_SIZE * sizeof(TCHAR),  // 버퍼 사이즈

                        &bytesRead, // 수신한 바이트 수

                        NULL);      

        if (! isSuccess && GetLastError() != ERROR_MORE_DATA) 

            break; 

        

        readDataBuf[bytesRead] = 0; 

        _tprintf( _T("%s \n"), readDataBuf ); 

    }

    

    CloseHandle(hPipe); 

    return 0; 

}






+ Recent posts