アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんにちは。

非同期のプロセス間通信(パイプ)で詰まっています。
環境はWindowsで処理系はC++(Win32)です。
スレッドを用意して、

hPipe = ::CreateFile( L"\\\\.\\pipe\\pipename", GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ) ;

で作成し、OVERLAPPED構造体を

//
ZeroMemory( &so, sizeof( OVERLAPPED )) ;
sOverlapped.hEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ;

として、

const size_t bufsize = 16 ;
BYTE     buffer[ uBufSize ] ;
DWORD    dwNumberOfBytesRead ;

bRet = ::ReadFile( hPipe, buffer, bufsize, &dwNumberOfBytesRead, &so ) ;

で読み込みをしています。ReadFile関数はすぐ戻りbRetはFALSEで返ってくるため、GetLastErrorを調べて、
switch( ::GetLastError())
{
  case ERROR_IO_PENDING :
    bRet = ::GetOverlappedResult( hPipe, &so, &dwNumberOfBytesRead, FALSE ) ;
    break ;
}

としてWaitForMultipleObjectsでsOverlapped.hEventがシグナル状態になったら取得したデータの処理をしています。
シグナル状態になるならないに関わらず、上記のReadFileとGetOverlappedResultはループでぐるぐる回しています。

上記の状態で短いデータならよかったのですが、上記のReadFileで読み込み最大サイズの16バイトを超えてしまとうと、
残りの部分のみしか取得できませんでした。

0123456789ABCDEFabcdefg

というデータを受信しようとしたとき、後半のabcdefgだけしか取得できませんでした。
すべてのデータを正しく取得するにはどのようにしたらよいのでしょうか?

A 回答 (2件)

TeijigoTeatimeさん、こんにちは。



提示されたコードは受け側のコードですね。

送り側はどうやってますか?
CreateNamedPipeでパイプを生成している思いますが、その第5、第6引数に何を与えていますか?
パイプで送受信するバッファが16バイトしか用意されていないということはないですか。

この回答への補足

こんばんは。レスありがとうございます。
CreateNamedPipeは以下で作成しています。
hPipe = ::CreateNamedPipe( "\\\\.\\pipe\\commandersvc", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 10, 1024, 1024, 100, &secAttr ) ;
受信側で取りこぼしている感じがしてので上記のような質問をさせていただきました。

補足日時:2014/08/13 20:05
    • good
    • 1
この回答へのお礼

原因がわかりました。
オーバーラップで処理しているので
case ERROR_IO_PENDING :
のあとで、きちんとイベント待ちしてから処理すれば取得できることができました。
返答頂いたことでいろいろ考えることができました。
ありがとうございました。

お礼日時:2014/08/25 15:08

dwNumberOfBytesReadの数値はどうなってますか?

この回答への補足

こんにちは。
dwNumberOfBytesReadは7です。"abcdefg"だけが受信できている感じです。
受信側でずっとdwNumberOfBytesReadの中身を監視しても前半の部分が取得された形跡はありませんでした。

送信側では
bRet=::WriteFile(hPipe, "0123456789ABCDEFabcdefg",23,&dwWritten,&so) ;
で送信していますが、dwWrittenは23となっており全て送信されている感じです。

1回目のReadFileで"0123456789ABCDEF"が取得でき、2回目で残りを受信と期待していたのですがその通り動作していません。

補足日時:2014/08/07 13:14
    • good
    • 0
この回答へのお礼

原因がわかりました。
オーバーラップで処理しているので
case ERROR_IO_PENDING :
のあとで、きちんとイベント待ちしてから処理すれば取得できることができました。
返答頂いたことでいろいろ考えることができました。
ありがとうございました。

お礼日時:2014/08/25 15:08

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A