はかせのラボ

私の頭の中を書いていく雑記ブログです

プログラミング プロセス間通信をとりあえず作ってみた

あいさつ

どうも、はかせです。
今回はプロセス間通信を作ってみたので
それについて書きます。

プロセス間通信とは?

その名通りプロセス間で通信をやることです。
プロセスAで入力を受け取りプロセスBに入力を渡す
みたいなことが出来るようになります。

実装方法は何があるのか全ては把握してませんが
今回は名前付きパイプというものを使って実装しています。

これはパイプインスタンスを作成し
クライアント、サーバ双方が同じパイプに
データを流したり読み込んだりすることで
複数のプロセス間で通信を実現しています。

実装

まずはコードです。
サーバ

#include <stdio.h>
#include <windows.h>

int main() {
	HANDLE hPipe = INVALID_HANDLE_VALUE;
	hPipe = CreateNamedPipe(L"\\\\.\\pipe\\mypipe", //lpName
		PIPE_ACCESS_INBOUND,            // dwOpenMode
		PIPE_TYPE_BYTE | PIPE_WAIT,     // dwPipeMode
		1,                              // nMaxInstances
		0,                              // nOutBufferSize
		0,                              // nInBufferSize
		100,                            // nDefaultTimeOut
		NULL);                          // lpSecurityAttributes

	if (hPipe == INVALID_HANDLE_VALUE) {
		fprintf(stderr, "Couldn't create NamedPipe.");
		return 1;
	}
	if (!ConnectNamedPipe(hPipe, NULL)) {
		fprintf(stderr, "Couldn't connect to NamedPipe.");
		CloseHandle(hPipe);
		return 1;
	}

	while (1) {
		char szBuff[256];
		DWORD dwBytesRead;
		if (!ReadFile(hPipe, szBuff, sizeof(szBuff), &dwBytesRead, NULL)) {
			fprintf(stderr, "Couldn't read NamedPipe.");
			break;
		}
		if (!strncmp("EXIT", szBuff, 4)) { // Exit Check
			break;
		}
		szBuff[dwBytesRead] = '\0';
		printf("Server : %s", szBuff);
		Sleep(1);
	}
	FlushFileBuffers(hPipe);
	DisconnectNamedPipe(hPipe);
	CloseHandle(hPipe);
	return 0;
}

クライアント

#include <stdio.h>
#include <windows.h>

int main() {
	HANDLE hPipe = INVALID_HANDLE_VALUE;
	hPipe = CreateFile(L"\\\\.\\pipe\\mypipe",
		GENERIC_WRITE,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (hPipe == INVALID_HANDLE_VALUE) {
		fprintf(stderr, "Couldn't create NamedPipe.");
		return 1;
	}

	while (1) {
		char szBuff[255];
		DWORD dwBytesWritten;
		fgets(szBuff, sizeof(szBuff), stdin);
		if (!WriteFile(hPipe, szBuff, strlen(szBuff), &dwBytesWritten, NULL)) {
			fprintf(stderr, "Couldn't write NamedPipe.");
			break;
		}
		if (!strncmp("EXIT", szBuff, 4)) { // Exit Check
			break;
		}
	}
	CloseHandle(hPipe);
	return 0;
}

コードは参考記事からほぼそのままコピペしています。

このコードをそれぞれ別のexeとしてコンパイル
サーバ→クライアントの順で実行します。
サーバ側でパイプを作っているため先に実行しなければ
クライアント側でパイプを読み込むことが出来ないからです。

CreateNamedPipe

今回の肝となる関数です。
第一引数でパイプの名前を設定します。
名前の書き方は

<サーバ名>\pipe\<パイプ名>

っていう書き方をするらしいです。

第二引数ではこのパイプのデータの流れを設定します。

PIPE_ACCESS_DUPLEX	//クライアント↔サーバ
PIPE_ACCESS_INBOUND	//クライアント→サーバ
PIPE_ACCESS_OUTBOUND    //クライアント←サーバ

残りはテンプレです。

実行結果

f:id:hakase0274:20190324232545p:plain

クライアントの入力がサーバに送られていることがわかります。

あとがき

今回はプロセス間通信でした。
作ってみようと思ったのはDirectX11を使ったアプリで
テキストで入力するうまい方法が思いつかず、
裏で別アプリ走らせて結果を取得しようと思ったからです。
(ただのテキスト入力で別アプリ使うってのは効率悪そうだけど)

もしテキスト入力を行ううまい方法があれば教えてください(__)

それでは今回はこの辺でノシ