Sunday, April 5, 2015

Visual C++ Pipe Server/Client 통신 예제

Win32에서 IPC(Inter Process Communication)의 하나의 방법인 Pipe에 관한 간단한 Server/Client 예제이다.
파이프를 하나만 만들고 단방향 서버 클라이언트이다.
서버는 보내기만 하고, 클라이언트는 받기만 한다.

// PipeServer2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
 // "\\\\.\\pipe\\RenToImaging"라는 이름의 파이프를 생성한다.
 // 파이프는 항상 \\.\pipe\(이름)에 생성 되어야 한다.
 HANDLE hPipe = ::CreateNamedPipe(L"\\\\.\\pipe\\RenToImaging",
  PIPE_ACCESS_DUPLEX, // 양방향
  PIPE_TYPE_BYTE, // 텍스트 모드
  255, // 최대 255개 인스턴스
  4096, // 출력 버퍼
  0, // 입력 버퍼
  1, // 타임아웃
  NULL);// 보안속성
 while(true)
 {
  // 이전에 연결된 파이프가 있는지 초기화 한다.
  ::DisconnectNamedPipe(hPipe);
  // 클라이언트가 연결되기를 기다린다.
  // 클라이언트가 연결되기 전에는 리턴되지 않는다.
  BOOL bCon = ::ConnectNamedPipe(hPipe, NULL);

  // bCon이 FALSE이고 GetLastError가 ERROR_PIPE_CONNECTED이면 정상 연결된 경우이므로 bCon을 TRUE로 해준다.
  if(bCon == FALSE && ::GetLastError() == ERROR_PIPE_CONNECTED)
   bCon = TRUE;
  // 정상 연결일 경우
  if(bCon == TRUE)
  {
   // WriteFile로 "Server"라는 문자열을 보내준다.
   DWORD written;
   BOOL bSuc = ::WriteFile(hPipe, L"Server", sizeof(wchar_t)*6, &written, NULL);
   ::wprintf(L"Connect\n");
   ::OutputDebugString(L"Connect\n");
   // 버퍼에 있는것을 비우고 파이프를 Disconnect한다.
   ::FlushFileBuffers(hPipe);
   ::DisconnectNamedPipe(hPipe);
  }
  else
  {
   // 연결이 실패한 경우이다.
   ::wprintf(L"Connect fail..\n");
   break;
  }
 }

 // 파이프를 닫아준다.
 ::CloseHandle(hPipe);
 return 0;
}


// PipeClient2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
 while(true)
 {
  HANDLE hPipe = NULL;
  for(;;)
  {
   // 파이프가 연결될 수 있는 상태까지 대기한다.
   if(::WaitNamedPipe(L"\\\\.\\pipe\\RenToImaging", NMPWAIT_WAIT_FOREVER) == TRUE)
   {
    ::OutputDebugString(L"Wait\n");
    ::wprintf(L"Wait\n");
    // 파이프를 생성한다.
    // 일반 파일과 동일하게 읽는다.
    hPipe = ::CreateFile(L"\\\\.\\pipe\\RenToImaging", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if(hPipe != INVALID_HANDLE_VALUE)
     break;
   }
  }
  ::OutputDebugString(L"CreateFile\n");
  ::wprintf(L"CreateFile\n");
  wchar_t wszBuffer[512] = {0,};
  DWORD dwWritten;
  // 파이프로부터 데이터를 전송 받는다.
  BOOL bRet = ::ReadFile(hPipe, wszBuffer, 512, &dwWritten, NULL);
  BYTE* pBuffer = (BYTE*)wszBuffer;
  pBuffer += sizeof(size_t)*2;
  ::wprintf(L"%s\n", (wchar_t*)pBuffer);
  // 파이프를 닫는다.
  ::FlushFileBuffers(hPipe);
  ::CloseHandle(hPipe);
  // 잠시쉬고 다시 처음으로 돌아가 서버의 전송을 기다린다.
  ::Sleep(200);
 }
 return 0;
}

No comments:

Post a Comment