일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- stream
- mfc
- length
- public
- sensor
- APP
- Read
- aduino
- memory
- file access
- Barcode
- parameter
- atmega328
- wpf
- Class
- SERIAL
- Contour
- Encapusulation
- digitalRead
- flutter
- java
- c++
- 3D
- inheritance
- Unity
- UNO
- Android
- compare
- Pointer
- preprocessing
- Today
- Total
폴크(FOLC)
데이터 공유 방법 ( 다른 PC ) 본문
Named Pipe 방식 (CreateNamedPipe)
1. 개요
- Windows에서 제공하는 고속 메모리 기반 IPC (Inter-Process Communication) 방식
- 프로세스 간 실시간으로 스트림 혹은 메시지를 전송할 수 있음
- 파일처럼 보이지만 진짜 파일은 아님
구성 요소
- 서버 프로세스:
- CreateNamedPipe 로 파이프 생성
- ConnectNamedPipe 로 클라이언트 연결 수신
- 클라이언트 프로세스:
- CreateFile 로 파이프에 연결
- WriteFile, ReadFile 로 데이터 송수신
동작 흐름
- 서버가 \\.\pipe\MyPipe 라는 파이프를 생성
- 클라이언트가 해당 파이프에 연결 시도
- 연결 후 실시간 데이터 전송 가능 (버퍼 기반)
장점
- 실시간성 우수 (메모리 기반 통신)
- 디스크 접근이 없어 빠름
- 읽기/쓰기 작업이 블로킹 또는 논블로킹으로 동작 가능
- 양방향 통신 가능 (Full Duplex)
단점
- 구현이 복잡 (에러 처리, 상태 관리 등 필요)
- 클라이언트 연결 시도 시 시간 제한/대기 처리 필요
- 보안 설정이 까다로울 수 있음 (다른 PC 간 통신 시)
< 예제 코드 >
서버 코드 -------
#include <windows.h>
#include <iostream>
#define PIPE_NAME L"\\\\.\\pipe\\MyNamedPipe"
-> \\\\.\\pipe\\ : Windows의 Named Pipe 네임스페이스 (특수 시스템 경로)
-> MyNamedPipe : 사용자가 지정한 파이프 이름 (고유 ID 역할)
-> 만약 원격 PC 와 연동해서 사용하는 경우에는
( 서버 쪽에서 CreateNamedPipe(L"\\\\.\\pipe\\MyNamedPipe") 로 생성한 파이프에, 클라이언트가 CreateFile(L" \\\\192.168.0.101\\pipe\\MyNamedPipe") 로 접속하는 구조입니다.
int main()
{
HANDLE hPipe = CreateNamedPipeW(
PIPE_NAME, // 파이프 이름
PIPE_ACCESS_DUPLEX, // 읽기/쓰기 양방향
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1, // 인스턴스 수 (동시 연결 허용 수)
1024, 1024, // 출력/입력 버퍼 크기
0, // 시간 제한 (기본값)
NULL); // 보안 속성
if (hPipe == INVALID_HANDLE_VALUE) {
std::cerr << "CreateNamedPipe 실패! 오류: " << GetLastError() << std::endl;
return 1;
}
std::wcout << L"클라이언트 연결 대기 중..." << std::endl;
BOOL connected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (connected) {
std::wcout << L"클라이언트 연결됨!" << std::endl;
char buffer[1024] = {0};
DWORD bytesRead;
if (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL)) {
std::cout << "[수신]: " << buffer << std::endl;
// 응답 메시지 전송
const char* reply = "서버에서 응답 보냄!";
DWORD bytesWritten;
WriteFile(hPipe, reply, strlen(reply), &bytesWritten, NULL);
std::cout << "[응답 전송 완료]" << std::endl;
} else {
std::cerr << "ReadFile 실패!" << std::endl;
}
} else {
std::cerr << "ConnectNamedPipe 실패!" << std::endl;
}
CloseHandle(hPipe);
return 0;
}
클라이언트 코드 -----
#include <windows.h>
#include <iostream>
#define PIPE_NAME L"\\\\192.168.0.101\\pipe\\MyNamedPipe "
-> \\\\.\\pipe\\ : Windows의 Named Pipe 네임스페이스 (특수 시스템 경로)
-> MyNamedPipe : 사용자가 지정한 파이프 이름 (고유 ID 역할)
-> 만약 원격 PC 와 연동해서 사용하는 경우에는
( 서버 쪽에서 CreateNamedPipe(L"\\\\.\\pipe\\MyNamedPipe") 로 생성한 파이프에, 클라이언트가 CreateFile(L" \\\\192.168.0.101\\pipe\\MyNamedPipe") 로 접속하는 구조입니다.
int main()
{
HANDLE hPipe = INVALID_HANDLE_VALUE;
// 무한 재시도 루프
while (true) {
hPipe = CreateFileW(
PIPE_NAME, // 서버의 파이프 이름
GENERIC_READ | GENERIC_WRITE,
0, NULL,
OPEN_EXISTING,
0, NULL
);
if (hPipe != INVALID_HANDLE_VALUE) {
std::cout << "파이프 연결 성공!" << std::endl;
break;
}
DWORD error = GetLastError();
if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PIPE_BUSY) {
std::cout << "서버 대기 중... 1초 후 재시도" << std::endl;
Sleep(1000); // 1초 대기 후 재시도
continue;
} else {
std::cerr << "파이프 연결 실패! 오류: " << error << std::endl;
return 1;
}
}
// 클라이언트 메시지 전송
const char* message = "클라이언트가 보낸 메시지입니다.";
DWORD bytesWritten;
WriteFile(hPipe, message, strlen(message), &bytesWritten, NULL);
std::cout << "보냄: " << message << std::endl;
// 서버로부터 응답 수신
char buffer[1024] = {0};
DWORD bytesRead;
ReadFile(hPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL);
std::cout << "응답 수신: " << buffer << std::endl;
// 연결 종료
CloseHandle(hPipe);
return 0;
}