1

名前付きパイプを使用してサーバー/クライアントを実装したい (IPC 用)。非同期 (オーバーラップ) 接続と I/O 完了ポートを使用しています (よく検索したところ、それが最も効率的な方法のようです)。 .

まず、コードは次のとおりです。

サーバー: http://pastebin.com/XxeXdunC

クライアント: http://pastebin.com/fbCH2By8

問題はサーバーにあります(クライアントを改善できますが、サーバーが機能するときにそれを行います)。

私はそのような I/O 完了ポートを使用します。基本的に、ReadFile() を呼び出すスレッドを実行します。TRUE が返された場合、すべてのデータを取得します。FALSE が返され、エラーが ERROR_IO_PENDING の場合は、GetQueuedCompletionStatus() で待機します。

奇妙なのは、すべてのデータを読み取ったとしても、最後の ReadFile() 呼び出しが失敗し、エラーが ERROR_IO_PENDING であることです。

ReadFile() を呼び出すスレッドは、サーバー コードの 64 行目から始まります。

クライアントは 24 バイト (文字列 "salut, c'est le client !") を送信し、ReadFile() バッファーの長さは 5 バイトです (サーバーが Readfile() バッファーよりも大きいデータを処理する方法を確認するため)。

出力は次のとおりです。

waiting for client...
WaitForMultipleObjects : 0
client connected (1)
ReadFile 1 msg (5 -> 05) : salut
ReadFile 2 msg (5 -> 10) : salut, c'e
ReadFile 2 msg (5 -> 15) : salut, c'est le
ReadFile 2 msg (5 -> 20) : salut, c'est le clie
ReadFile 2 msg (4 -> 24) : salut, c'est le client !
ReadFile2: ERROR_IO_PENDING
GQCIOS 0 255 003D3A18
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
GQCIOS 5 255 003D3A2C
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
GQCIOS 5 255 003D3A2C
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
GQCIOS 5 255 003D3A2C
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
GQCIOS 5 255 003D3A2C
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
GQCIOS 4 255 003D3A2C
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING

私が理解していないのは、すべてのデータを読み取っても、ReadFile() がまだ保留中の操作を返すことです (最後の「msg」出力の後の「ReadFile2: ERROR_IO_PENDING」エラー メッセージです)。

私のループは間違っていますか?ReadFile() / GetQueuedCompletionStatus() を誤用していませんか?

ありがとうございました

4

1 に答える 1

1

書き込み関連の機能はどこにありますか? コードの順序が間違っているようです。_read_data_cbルーチンでは、GetQueuedCompletionStatus最初に を呼び出す必要があります。次に、パラメーターに応じてlpOverlapped、受信したデータが ReadFile 関数で指定したバッファーに準備されている必要があります。OVERLAPPEDsend コンテキストまたは recv コンテキストの構造が重複しているかどうかを確認せずに Readfile を呼び出しているため、期待される出力が得られません。次のコードは問題を解決するはずです:

while(TRUE)
{
    bReturnValue=GetQueuedCompletionStatus(pIOCPServer->m_pIOCP, &dwBytesTransferred,(DWORD *)pClient,reinterpret_cast<LPOVERLAPPED*>(&pOverlapped),INFINITE);
    if(!bReturnValue)
    {
        if(NULL==pOverlapped)
            continue;
        else
            break;
    }
    else
    {
        if(pOverlapped==NULL)
            continue;
    }
    if(dwBytesTransferred==0)
        break;
    if(lpOverlapped==&(pClient->m_pRecvContext->overlapped))
        pClient->handleRecvEvent(dwBytesTransferred)
    else if(lpOverlapped==&(pClient->m_pSendContext->overlapped))
        pClient->handleSendEvent(dwBytesTransferred)
}
...
于 2011-05-22T09:23:31.100 に答える