名前付きパイプを用いたプロセス間通信


CreateNamedPipeでパイプを作成し、プロセス間でそのパイプに対してデータの読み書きを行うことでデータのやり取りを行う。WindowsAPIのReadFileやWriteFileを用いて、ファイルに読み書きする感覚で通信ができる。

■サーバ側


void Server::CreatePipe() {

// 名前付きパイプを作成する
HANDLE hPipe = CreateNamedPipe(
"\\\\.\\pipe\\test",
PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1, 1024, 1024, 0, NULL);

// イベントを作成する(初期状態は非シグナル指定)
HANDLE hEvent = CreateEvent(NULL, true, false, "test");

while (1) {
// クライアントがパイプに接続するまで待つ
ConnectNamedPipe(hPipe, NULL);

// クライアントがパイプに書き込み終わるまで待つ
WaitForSingleObject(hEvent, INFINITE);
ResetEvent(hEvent);

byte[] buffer = new byte[MAX_LOG_MSG];
int readBytes = 0;
// クライアントがパイプに書き込んだ内容を読み込む
ReadFile(hPipe, pBuffer, GetFileSize(hPipe), &readBytes, NULL);

// パイプを切断する
DisconnectNamedPipe(hPipe);
}
}

■クライアント側


void Client::CreatePipe(const char* buf) {

// サーバ側で作成したイベントを開く
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, false, "test");

// パイプに接続する
HANDLE hPipe = CreateFile(
"\\\\.\\pipe\\test", GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

// パイプの切断が適切に行われていない場合ERROR_PIPE_BUSYとなる
int errorNo = GetLastError();
if (errorNo == ERROR_PIPE_BUSY) {
// エラー処理
}

int writeBytes = 0;
// パイプに書き込む
WriteFile(hPipe, buf, strlen(buf), &writeBytes, NULL);

// 書き込み終了をサーバに伝える
SetEvent(hEvent);
}