広告

posted by fanblog

2015年01月26日

いまさらながらの Mailslot

近頃セッション境界を越えてメッセージを送信したい要求が出てきて、やりたいことと仕掛けのバランスがよいものを探していたのだが、ふと、昔読んだ本の内容を思い出し、メールスロットなるものを使ってみた

元々の要求は、異なるプロセスから一方向でメッセージを送信したいというもので、普通にやるなら引数と SendMessage で済む程度の簡単なものなのだったが、セッション境界を越えて渡せないことに気が付き、はたと困ったのであった
こうした欲求を満たすには、大掛かりなものでは TCP で TELNET プロトコルを実装するなどをしてきたのだが、ポートの割り当て問題などがあり、ちょっと面倒
名前付きパイプが妥当そうに見えたのだが、API がごちゃごちゃしていて、あまり使い勝手がよくないと感じた(双方向通信なら、こちらがいいかもしれない)

そこで、一方向で済む、メールスロットを思い出したのだが、そもそもこの機構はかなり古い時代から存在するので、今では DDE のように化石扱いなのではないかと心配になった
API の解説を読む限りは、シンプルで最低限のセキュリティを備えているので、まだまだ現役で使えそうではある

サーバの簡単な実装は以下のようである

HANDLE g_hServer = CreateMailslotW(SERVER_NAME, MESSAGE_SIZE, SERVER_TIMEOUT, NULL);
while (true) {
DWORD cnt = 0;
if (!GetMailslotInfo(g_hServer, NULL, NULL, &cnt, NULL)) {
fprintf(stderr, "GetMailslotInfo failed by %d\n", GetLastError());
break;
}
if (cnt > 0) {
CHAR szMessage[MESSAGE_SIZE+1] = {0};
DWORD dwRead;
OVERLAPPED ovl = {0};
ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
BOOL rc = ReadFile(g_hServer, szMessage, MESSAGE_SIZE, &dwRead, &ovl);
CloseHandle(ovl.hEvent);
if (!rc) {
fprintf(stderr, "ReadFile failed by %d\n", GetLastError());
break;
}
printf("%s\n", szMessage);
}
Sleep(100);
}
CloseHandle(g_hServer);


途中、 if (cnt > 0) としてあるところは、 for (DWORD j = 0; j < cnt; j++) とすべきかもしれない

一方、クライアント側は単純にファイルに書き込むだけでよい
以下のよう

HANDLE hFile = CreateFile(SERVER_NAME, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == hFile) {
fprintf(stderr, "CreateFile failed by %d\n", GetLastError());
return 1;
}
CHAR szMessage[] = "Hello world";
DWORD dwSize;
if (!WriteFile(hFile, szMessage, strlen(szMessage), &dwSize, NULL)) {
fprintf(stderr, "WriteFile failed by %d\n", GetLastError());
}
CloseHandle(hFile);


実に単純な構成だが、セッション超えには実はもう一つ落とし穴があった





この記事へのコメント
コメントを書く

お名前:

メールアドレス:


ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバックURL
https://fanblogs.jp/tb/3212018
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック
Build a Mobile Site
スマートフォン版を閲覧 | PC版を閲覧
Share by: