[an error occurred while processing this directive]
[an error occurred while processing this directive]c:\> pipe_server.exe hogeみたいに引数をなんかつけて実行すると、サーバーモードで、新しく名前付きpipeを作ります。
c:\> pipe_server.exeみたいに引数をつけないと、クライアントモードで、既存の名前付きpipeに接続します。
// pipe_server.cpp : パイプのサンプル
//
// includeするもの:
// #include <windows.h>
// #include <conio.h>
// #include <process.h>
// #include <iostream>
#include "stdafx.h"
#define PIPE_NAME "\\\\.\\pipe\\hello_pipe3"
#define TIME_OUT 120 * 1000
bool debug = false;
/** エラーを表示して終了する */
void err_exit(char *cp){
DWORD eno = GetLastError();
std::cerr << "Error: " << cp << " errcode=" << eno << std::endl;
ExitProcess(eno);
}
/** エラーを表示して、パイプを閉じて終了する */
void err_close_exit(char *cp, HANDLE h){
int eno = GetLastError();
std::cerr << "Error: " << cp << " errcode=" << eno << std::endl;
CloseHandle(h);
ExitProcess(eno);
}
class PipeBase {
/**
* パイプのベースクラス (read/writeを備える)
*/
protected:
HANDLE hPipe;
public:
void read(char *buf, int buflen, int read_len){
/** バッファbuf(長さbuflen)に、read_lenで指定されたバイト数読み込む。*/
int already_read = 0;
if(read_len >= buflen)
err_close_exit("Too small buffer", hPipe);
while(already_read < read_len){
DWORD actual_len;
int ret = ReadFile(hPipe, buf + already_read, read_len - already_read, &actual_len, NULL);
if(debug)
std::cout << "Read "<< actual_len << " bytes" << std::endl;
already_read += actual_len;
if(!ret) err_close_exit("ReadFile", hPipe);
}
// おせっかいかもしれないけど、coutとかでうまく表示できるように最後を\0でつぶしておく。
buf[read_len] = '\0';
if(debug) std::cout << "Server read: " << buf << std::endl;
}
void write(char *buf, int write_len){
if(debug)
std::cerr << "% Writing to HANDLE " << hPipe << std::endl;
/** バッファbufから、write_lenで指定されたバイト数書き込む。*/
int already_written = 0;
while(already_written < write_len){
DWORD actual_len;
int ret = WriteFile(hPipe, buf + already_written, write_len - already_written, &actual_len, NULL);
if(debug)
std::cout << "% Wrote "<< actual_len << " bytes" << " (tried to write " << write_len << ")" << std::endl;
already_written += actual_len;
if(!ret) err_close_exit("WriteFile", hPipe);
}
}
};
class PipeServer : public PipeBase {
/** パイプのサーバ (名前付きパイプを作り、clientからの入力を待つ) */
public:
PipeServer(char *pipe_name, int dwBufferSize = 1024){
/**
* コンストラクタ。
* パイプを作り、クライアントの接続を待つ。
*/
hPipe = CreateNamedPipe(
pipe_name, /* パイプ名 */
PIPE_ACCESS_DUPLEX, /* 双方向 */
PIPE_WAIT /* ブロッキング・モード */
| PIPE_READMODE_BYTE /* バイト・モード */
| PIPE_TYPE_BYTE,
PIPE_UNLIMITED_INSTANCES, /* インスタンス数の制限なし */
dwBufferSize, /* 出力バッファ・サイズ */
dwBufferSize, /* 入力バッファ・サイズ */
TIME_OUT, /* タイムアウト */
NULL); /* セキュリティ属性なし */
if(hPipe == INVALID_HANDLE_VALUE){
int eno = GetLastError();
if(eno == 123){
std::cerr << "Pipename format is wrong" << std::endl;
ExitProcess(eno);
} else {
err_exit("CreateNamedPipe");
}
}
if(debug)
std::cerr << "% Pipe has successfully created" << std::endl;
// クライアントの接続待ち
int ret = ConnectNamedPipe(hPipe, NULL);
if(!ret) err_close_exit("ConnectNamedPipe", hPipe);
if(debug) std::cerr << "% Client has connected" << std::endl;
}
~PipeServer(){ CloseHandle(hPipe);}
};
class PipeClient : public PipeBase {
/** パイプのクライアント (名前付きパイプを作り、サーバに接続する) */
public:
PipeClient(char *pipe_name, int dwBufferSize = 1024){
/**
* コンストラクタ。
* 名前を指定して、パイプに接続する。
*/
hPipe = CreateFile(pipe_name, /* パイプ名 */
GENERIC_WRITE | GENERIC_READ, /* 読み書きアクセス */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* 読み書きアクセス共有 */
NULL, /* セキュリティ属性なし */
OPEN_EXISTING, /* 既存の名前付きパイプに接続 */
FILE_ATTRIBUTE_NORMAL, /* ファイル属性なし */
NULL); /* テンプレート・ファイルなし */
std::cerr << "HANDLE " << hPipe << std::endl;
if (hPipe == INVALID_HANDLE_VALUE) {
int eno = GetLastError();
if(eno == ERROR_FILE_NOT_FOUND){
std::cerr << "Specified Pipe Not Found" << std::endl;
ExitProcess(eno);
} else {
err_exit("CreateFile");
}
}
if(debug) std::cerr << "Successfully connected to the named-pipe" << std::endl;
}
~PipeClient(){ CloseHandle(hPipe);}
};
int main(int argc, char* argv[])
{
if(argc == 2){
PipeServer ps(PIPE_NAME);
const int LEN = 1024;
char buf[LEN];
ps.read(buf, LEN, 5);
std::cerr << "Received " << buf << std::endl;
} else {
char *cp = "hello";
PipeClient pc(PIPE_NAME);
pc.write(cp, 5);
Sleep(100);
std::cerr << "Sent " << cp << std::endl;
}
return 0;
}