프로그래밍 노트

유명한 파이프 만들기 CreateNamedPipe (서버쪽) 본문

Win32 SDK 초보

유명한 파이프 만들기 CreateNamedPipe (서버쪽)

띠리 2007. 4. 19. 12:52

파이프를 만들면 클라이언트가 접속하는 것을 기다려야된다.
일반적으로 스래드를 만들어 기다리게 한다.
이 예제는 클라이언트에서 보낸 자료를 표시하게만 한다.
스레드는 영구 루프로 만들고 그 안에서 ReadFile함수를 호출한다.
클라이언트가 아무것도 쓰지 않았을때에 ReadFile을 하면 에러가 됨으로
대기 함수를 사용하여 이벤트를 기다리는 것으로 한다.
클라이언트 쪽에서 쓰기 직전에 이벤트를 시그널 상태로 한다.
루프 안에서 읽기가 끝나면 바로 이벤트를 비시그널 상태로 하고 다음의 쓰기를 기다리는 상태로 한다.
프로그램을 종료 할때는 클라이언트 쪽에서 quit라 써서 보낸다.
서버쪽에서는 읽어들인 문자열이 quit이면 루프에서 빠져나와 처리를 종료한다.

main 함수
이름있는 파이프를 만들고 이벤트를 만든다.
이벤트는 초기 상태로 시그널 상태가 아니다.
스레드를 만들지 않으면 그냥 프로그램이 끝나기 때문에
스레드를 만들어 클라이언트 쪽의 데이터를 기다린다.


스레드 함수
무한루프에 들어가면 WaitForSingleObject함수로 대기한다.
클라이언트쪽에서 데이터를 보내면 이벤트를 시그널 상태로 해서
파이프로부터 전해진 내용을 읽는다.
읽고난 후 바로 이벤트를 시그널이 아닌 상태로 한다.
클라이언트 쪽에서 보내온 데이터가 "quit"인 경우 무한루프에서 빠져나온다.
루프에서 빠져 나오면 이벤트를 시그널 상태로 한다.(클라이언트 쪽을 고려해서...)


======================================================================

#include <stdio.h>

#include <windows.h>

#include <conio.h>

#include <process.h>


#define EvtName        "PipeEvent"

#define PipeName    "\\\\.\\pipe\\TestPipe"


unsigned __stdcall ReadPipeThreadProc(LPVOID);


HANDLE hEvent, hThread;


int main()

{

    unsigned        usThreadID;

    static HANDLE    hPipe;


    hPipe = CreateNamedPipe(PipeName,

                PIPE_ACCESS_INBOUND,    // 오픈 모드

                PIPE_TYPE_BYTE |

                PIPE_READMODE_BYTE |

                PIPE_WAIT,                // 파이프 모드

                1,                        // 파이프 최대 인스턴스 갯수

                1024,                    // 출력 버퍼

                1024,                    // 입력 버퍼

                0,                        // 타임 아웃

                NULL);


    if (hPipe == INVALID_HANDLE_VALUE)

    {

        printf( "파이프 만들기 실패\");

        return -1;

    } else

    {

        printf("파이프 만들기 성공\");

    }


    hEvent = CreateEvent(NULL,            // 시큐리티 속성

                FALSE,                    // 수동 리셋

                FALSE,                    // 초기 상태

                EvtName);                // 이벤트명


    hThread = (HANDLE)_beginthreadex(NULL,

                0,

                &ReadPipeThreadProc,

                (LPVOID)hPipe,

                0,

                &usThreadID);


    if (hThread == NULL)

    {

        printf("스레드 만들기 실패\");

        CloseHandle(hPipe);

        return -3;

    } else

    {

        printf("스레드 만들기 성공\");

    }


    WaitForSingleObject(hThread, INFINITE);


    if (CloseHandle(hThread))

    {

        printf("스레드의 핸들 클로즈\");

    }


    printf("프로그램을 종료합니다.\n");

    printf("아무 키나 눌러주세요.\n");


    // 콘솔창이 자동으로 닫히지 않게하기

    _getch();


    return 0;

}


unsigned __stdcall ReadPipeThreadProc(LPVOID lpParam)

{

    char    szBuf[1024];

    HANDLE    hPipe;

    DWORD    dwRead;

    BOOL    bRead = FALSE;


    printf("클라이언트의 송신 대기중\");

    hPipe = (HANDLE)lpParam;


    while (1)

    {

        WaitForSingleObject(hEvent, INFINITE);


        memset(szBuf, '\0', sizeof(szBuf));


        bRead = ReadFile(hPipe,

                        szBuf,

                        sizeof(szBuf),

                        &dwRead,

                        NULL);


        ResetEvent(hEvent);


        if (bRead == FALSE)

        {

            MessageBox(NULL, "읽기 실패", "Error", MB_OK);

            break;

        }


        printf("%s\n", szBuf);


        if (strcmp(szBuf, "quit") == 0)

        {

            break;

        }

    }


    printf("파이프 읽기 루프 탈출\");


    SetEvent(hEvent);


    if (CloseHandle(hPipe))

    {

        printf("파이프 닫기\");

        printf("스레드 종료\");

    }


    return 0;

}




======================================================================

이 프로그램은 Win32콘솔 응용 프로그램으로 빈 프로젝트를 만들어
C++파일을 만들어 위 코드를 붙여서 빌드만 하면 됩니다.

Comments