티스토리 뷰

책 : 뇌를 자극하는 윈도우즈 시스템 프로그래밍

 

파이프에는 두가지 종류가 있는데 이름없는 파이프(anonymous_pipe)와 이름있는 파이프(named_pip)가 있습니다. 

  anonymous_pipe 같은 경우에는 프로세스에서 내부 즉, 자식 프로세스나 부모 프로세스와 통신을 할때 사용하는 것으로, 외부 프로세스와는 통신 할 수 없습니다. 

  named_pipe 같은 경우에는 이름이 존재하기 때문에, 이름을 통하여 외부의 프로세스와 통신을 할 수 있다. 통신 방법은

아래와 같습니다.

 

아래는 서버와 클라이언트 코드입니다.

 

서버

더보기
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <windows.h> 
#include <tchar.h>

#define BUF_SIZE 1024

int CommToClient(HANDLE);

int _tmain(int argc, TCHAR* argv[])
{
	LPTSTR pipeName = (LPTSTR)_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)
{
	char 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;
	}
	fileName[fileNameSize] = L'\0';
	//_tprintf(_T("%s %d\n"), fileName, fileNameSize);
	printf("%s %d\n", fileName, fileNameSize);
	FILE* filePtr = fopen(fileName, "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;
}

 

클라이언트

더보기
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tchar.h>

#define BUF_SIZE 1024

int _tmain(int argc, TCHAR* argv[])
{
    HANDLE hPipe;
    TCHAR readDataBuf[BUF_SIZE + 1];
    LPTSTR pipeName = (LPTSTR)_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,             // 전송할 메시지 
        (strlen(fileName) * sizeof(TCHAR)), // 메시지 길이 
        &bytesWritten,             // 전송된 바이트 수
        NULL);
    _tprintf("%s %d %d\n", fileName, bytesWritten);
    if (!isSuccess)
    {
        _tprintf(_T("WriteFile failed"));
        return 0;
    }
    _tprintf(_T("WriteFile Succed : %s"), fileName);
    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);
    }
    getchar();
    CloseHandle(hPipe);
    return 0;
}

 

왠지는 모르겠는데, 서버에서 TCHAR 배열로 ReadFile 쓰니까 데이터가 제대로 안받아지더라구요. 그래서 어쩔 수 없이 char형태로 받았습니다..

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함