11

データを 1 バイト ストリームとして送信するように構成された名前付きパイプを使用して、2 つのアプリケーション間でシリアル化されたデータ構造を送信しています。シリアル化されたデータは、サイズが大幅に変化します。送信側では、これは問題ではありません。送信するバイト数を正確に調整できます。

受信 (読み取り) 側のバッファーを、読み取る正確なバイト数に設定するにはどうすればよいですか? 送信(書き込み)側のデータの大きさを知る方法はありますか?

PeekNamedPipe を見てきましたが、この関数はバイト型の名前付きパイプには役に立たないように見えますか?

lpBytesLeftThisMessage [出力、オプション] このメッセージに残っているバイト数を受け取る変数へのポインター。バイト型の名前付きパイプまたは匿名パイプの場合、このパラメーターはゼロになります。データを読み取る必要がない場合、このパラメーターは NULL にすることができます。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365779(v=vs.85).aspx

必要なバッファ サイズを正確に判断できない場合、このような状況をどのように処理するのが最善でしょうか?

送信コード

    string strData;
strData =  "ShortLittleString";

DWORD numBytesWritten = 0;
result = WriteFile(
    pipe, // handle to our outbound pipe
    strData.c_str(), // data to send
    strData.length(), // length of data to send (bytes)
    &numBytesWritten, // will store actual amount of data sent
    NULL // not using overlapped IO
);

読み取りコード:

DWORD numBytesToRead0 = 0;
DWORD numBytesToRead1 = 0;
DWORD numBytesToRead2 = 0;

BOOL result = PeekNamedPipe(
pipe,
NULL,
42,
&numBytesToRead0,
&numBytesToRead1,
&numBytesToRead2
);

char * buffer ;

buffer = new char[numBytesToRead2];

char data[1024]; //1024 is way too big and numBytesToRead2 is always 0 
DWORD _numBytesRead = 0;

BOOL    result = ReadFile(
pipe,
data, // the data from the pipe will be put here
1024, // number of bytes allocated
&_numBytesRead, // this will store number of bytes actually read
NULL // not using overlapped IO
);

上記のコードでは、PeakNamedPipe 関数がすべてのnumBytesToRead変数に対して 0 を返すため、バッファーのサイズは常に 0 です。このバッファサイズを正確に設定する方法はありますか? そうでない場合、そのような状況を処理する最善の方法は何ですか? 助けてくれてありがとう!

4

2 に答える 2

6

lpTotalBytesAvail送信データサイズを取得できなかったのはなぜだと思いますか? バイトモードでは常に機能します。常にゼロの場合は、何か間違ったことをした可能性があります。また、データ バッファーとして使用することをお勧めします。std::vector生のポインターやnewステートメントをいじるよりもはるかに安全です。

lpTotalBytesAvail [out, optional]パイプから読み取ることができる合計バイト数を受け取る変数へのポインター。データを読み取る必要がない場合、このパラメーターは NULL にすることができます。

サンプルコード:

// Get data size available from pipe
DWORD bytesAvail = 0;
BOOL isOK = PeekNamedPipe(hPipe, NULL, 0, NULL, &bytesAvail, NULL);
if(!isOK)
{
   // Check GetLastError() code
}

// Allocate buffer and peek data from pipe
DWORD bytesRead = 0;    
std::vector<char> buffer(bytesAvail);
isOK = PeekNamedPipe(hPipe, &buffer[0], bytesAvail, &bytesRead, NULL, NULL);
if(!isOK)
{
   // Check GetLastError() code
}
于 2012-09-22T11:47:20.753 に答える
1

さて、あなたは ReadFile() を使用しています。ドキュメントには、とりわけ次のように記載されています。

名前付きパイプがメッセージ モードで読み取られており、次のメッセージが nNumberOfBytesToRead パラメータで指定された長さよりも長い場合、ReadFile は FALSE を返し、GetLastError は ERROR_MORE_DATA を返します。メッセージの残りの部分は、その後 ReadFile または PeekNamedPipe 関数を呼び出すことで読み取ることができます。

あなたはそれを試しましたか?私はこのようなパイプを使用したことがありません:-)、子プロセスの標準入力/出力ハンドルに到達するためにのみ使用しました。

上記は必要に応じて何度でも繰り返すことができると想定しているため、「メッセージの残り」はやや不正確な説明になります。「残り」がバッファに収まらない場合は、別の ERROR_MORE_DATA を取得するだけだと思います。残りの残りを取得することを知っています。

または、私があなたを完全に誤解していて、実際にこの「メッセージモード」を使用していない場合は、間違った方法で物事を読んでいるだけかもしれません. データの最後に到達するまで、固定サイズのバッファーを使用してデータを読み取り、最終ブロックに追加することができます。または、「固定」サイズのバッファのサイズを増やして、これを少し最適化します。

于 2012-09-22T10:50:19.007 に答える