웬디의 기묘한 이야기

글 작성자: WENDYS
반응형

PIPE Client


이전에 소개했던 Multithreaded pipe server에 이어 client code 입니다.

모든 server - client program이 그렇듯이 client는 간단 합니다.

하는일은 서버에 접속해서 데이터를 주고 받는게 다 입니다.


바로 코드로 보겠습니다.


생성자에서 서버 정보를 입력받아 바로 접속을 시도하고, 성공 실패여부는 verify 를 통하여 확인 가능하도록 했습니다.


파이프 서버는 생성할때 서버 이름을 입력해주어야 하고, 마찬가지로 클라이언트에서 접속할때도 서버 이름을 입력해야합니다.

이름은 \\\\.\\pipe\\mynamedpipe 형태로 생성 및 접근해야합니다.



namespace pipe {
class client {

public:
    client(
        __in LPCTSTR pipe_name,
        __in_opt const DWORD pipe_wait_timeout = NMPWAIT_WAIT_FOREVER
        ) {
        do {
            if (!pipe_name) {
                break;
            }

            if (!WaitNamedPipe(
                pipe_name,
                pipe_wait_timeout)
                ) {
                break;
            }

            _pipe = CreateFile(
                pipe_name,
                (GENERIC_READ | GENERIC_WRITE),
                0,
                nullptr,
                OPEN_EXISTING,
                0,
                nullptr
                );

            if (_pipe == INVALID_HANDLE_VALUE) {
                break;
            }

        } while (false);
    }

    ~client() {
        if (_pipe != INVALID_HANDLE_VALUE) {
            CloseHandle(_pipe);
        }
    }

    bool verify() const {
        return _pipe != INVALID_HANDLE_VALUE;
    }

    bool read(
        __out size_t& bytes_read,
        __out void* read_buffer,
        __in const size_t read_buffer_size
        ) {

        bool result = false;
        DWORD real_bytes_read = 0;

        do {
            if (!ReadFile(
                _pipe,
                read_buffer,
                static_cast<DWORD>(read_buffer_size),
                &real_bytes_read,
                nullptr)
                ) {
                break;
            }

            if (real_bytes_read == 0) {
                break;
            }

            bytes_read = real_bytes_read;
            result = true;
        } while (false);

        return result;
    }

    bool write(
        __out size_t& bytes_written,
        __in void* write_data,
        __in const size_t write_data_size
        ) {

        bool result = false;
        DWORD real_bytes_written = 0;

        do {
            if (!WriteFile(
                _pipe,
                write_data,
                static_cast<DWORD>(write_data_size),
                &real_bytes_written,
                nullptr)
                ) {
                break;
            }

            if (write_data_size != real_bytes_written) {
                break;
            }

            bytes_written = real_bytes_written;
            result = true;
        } while (false);

        return result;
    }

private:
    HANDLE _pipe;

};
} // namespace pipe


이렇게 만들었으면 어떻게 사용해야할지 모르는분들을 위해 테스트 코드 입니다.

단순하게 서버와 클라이언트를 생성하여 메시지를 전달했습니다.



#include<thread>

void run_server_thread() {
    pipe::server server(L"\\\\.\\pipe\\mynamedpipe", 10);
    server.accept();

    size_t size = 0;
    wchar_t buffer[512] = {};

    server.read(size, buffer, 512);
    server.write(size, buffer, 512);
}

void run_client_thread() {
    pipe::client client(L"\\\\.\\pipe\\mynamedpipe");

    size_t size = 0;
    wchar_t buffer[512] = L"test message";
    client.write(size, buffer, 512);

    wchar_t read_buffer[512] = {};
    client.read(size, read_buffer, 512);

    OutputDebugString(buffer);
}


void Cpipe_sampleDlg::OnBnClickedButton1()
{
    std::thread run_server = std::thread(run_server_thread);
    run_server.detach();
}


void Cpipe_sampleDlg::OnBnClickedButton2()
{
    std::thread run_client = std::thread(run_client_thread);
    run_client.detach();
}


모르겠다 싶은분들은 첨부파일을 다운받아 테스트 해보시기 바랍니다. (visual studio 2015 community version 입니다.)


pipe_sample.zip



반응형