C ++ Windows Asynch IO命名pipe道第一条消息没有收到

使用重叠I / O从命名pipe道服务器修改代码https://msdn.microsoft.com/en-us/library/windows/desktop/aa365603(v=vs.85).aspx

服务器代码如下所示:

#include <windows.h> #include <stdio.h> #include <tchar.h> #include <strsafe.h> #include <iostream> #define CONNECTING_STATE 0 #define READING_STATE 1 #define INSTANCES 4 #define PIPE_TIMEOUT 5000 #define BUFSIZE 4096 typedef struct { OVERLAPPED oOverlap; HANDLE hPipeInst; TCHAR chRequest[BUFSIZE]; DWORD cbRead; TCHAR chReply[BUFSIZE]; DWORD cbToWrite; DWORD dwState; BOOL fPendingIO; } PIPEINST, *LPPIPEINST; BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED); PIPEINST Pipe[INSTANCES]; HANDLE hEvents[INSTANCES]; int _tmain(VOID) { DWORD i, dwWait, cbRet, dwErr; BOOL fSuccess; LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); for (i = 0; i < INSTANCES; i++) { hEvents[i] = CreateEvent( NULL, // default security attribute FALSE, // manual-reset event TRUE, // initial state = signaled NULL); // unnamed event object if (hEvents[i] == NULL) { printf("CreateEvent failed with %d.\n", GetLastError()); return 0; } Pipe[i].oOverlap.hEvent = hEvents[i]; DWORD dwOpenMode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED; Pipe[i].oOverlap.Offset = 0; Pipe[i].oOverlap.OffsetHigh = 0; Pipe[i].hPipeInst = CreateNamedPipe( lpszPipename, dwOpenMode, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, INSTANCES, BUFSIZE*sizeof(TCHAR), BUFSIZE*sizeof(TCHAR), PIPE_TIMEOUT, NULL); if (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE) { printf("CreateNamedPipe failed with %d.\n", GetLastError()); return 0; } BOOL rc = ConnectNamedPipe(Pipe[i].hPipeInst, &Pipe[i].oOverlap); // Overlapped ConnectNamedPipe should return FALSE. if (!rc && GetLastError() == ERROR_PIPE_CONNECTED) { std::cout<<"pipe connected setting event " << std::endl; rc = SetEvent(&Pipe[i].oOverlap.hEvent); } else if (rc || GetLastError() != ERROR_IO_PENDING) { std::cout<<"exiting... " << std::endl; rc = CloseHandle(Pipe[i].hPipeInst); return 0; } }// for INSTANCES while (1) { dwWait = WaitForMultipleObjects( INSTANCES, // number of event objects hEvents, // array of event objects FALSE, // does not wait for all INFINITE); // waits indefinitely i = dwWait - WAIT_OBJECT_0; // determines which pipe if (i < 0 || i > (INSTANCES - 1)) { printf("Index out of range.\n"); return 0; } fSuccess = GetOverlappedResult( Pipe[i].hPipeInst, // handle to pipe &Pipe[i].oOverlap, // OVERLAPPED structure &cbRet, // bytes transferred FALSE); // do not wait std::cout<<"GetOverlappedResult " << cbRet; std::cout<<" success " << fSuccess; std::cout<<" state " << Pipe[i].dwState; std::cout<<" GetLastError " << GetLastError() << std::endl; fSuccess = ReadFile( Pipe[i].hPipeInst, Pipe[i].chRequest, BUFSIZE*sizeof(TCHAR), &Pipe[i].cbRead, &Pipe[i].oOverlap); if(!fSuccess) std::wcout<<L" Error: "<< GetLastError() <<std::endl; if (fSuccess && Pipe[i].cbRead != 0) { Pipe[i].fPendingIO = FALSE; Pipe[i].dwState = READING_STATE; std::wcout<<L"Message " << Pipe[i].chRequest << std::endl; continue; } dwErr = GetLastError(); if (! fSuccess && (dwErr == ERROR_IO_PENDING)) { std::cout<<"Error IO is still pending" << std::endl; Pipe[i].fPendingIO = TRUE; continue; } break; } return 0; } 

客户端代码如下:

  #include <windows.h> #include <stdio.h> #include <conio.h> #include <tchar.h> #include <string> #include <sstream> #include <time.h> #include <iostream> #define BUFSIZE 4096 int _tmain(int argc, TCHAR *argv[]) { HANDLE hPipe; TCHAR chBuf[BUFSIZE]; BOOL fSuccess = FALSE; DWORD cbRead, cbToWrite, cbWritten, dwMode; LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); BOOL rc; do { hPipe = CreateFileW(lpszPipename, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (hPipe == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_PIPE_BUSY) { // wait for the pipe to become available rc = WaitNamedPipeW(lpszPipename, NMPWAIT_USE_DEFAULT_WAIT); if (!rc) return false; } else { return false; } } } while (hPipe == INVALID_HANDLE_VALUE); dwMode = PIPE_READMODE_MESSAGE; fSuccess = SetNamedPipeHandleState( hPipe, // pipe handle &dwMode, // new pipe mode NULL, // don't set maximum bytes NULL); // don't set maximum time if ( ! fSuccess) { _tprintf( TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError() ); return -1; } //=================================================================== while(1) { std::cout<<"press a key to send " << std::endl; _getch(); fSuccess = WriteFile( hPipe, "A", 1, &cbWritten, NULL); if ( ! fSuccess) { _tprintf( TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError() ); return -1; } fSuccess = WriteFile( hPipe, "B", 1, &cbWritten, NULL); if ( ! fSuccess) { _tprintf( TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError() ); return -1; } //Sleep(1000); fSuccess = WriteFile( hPipe, "C", 1, &cbWritten, NULL); if ( ! fSuccess) { _tprintf( TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError() ); return -1; } fSuccess = WriteFile( hPipe, "D", 1, &cbWritten, NULL); if ( ! fSuccess) { _tprintf( TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError() ); return -1; } }// loop printf("\n<End of message, press ENTER to terminate connection and exit>"); _getch(); CloseHandle(hPipe); return 0; 

}

服务器从来没有收到消息A,但B,C,D都收到了OK。 如果您在客户端中取消注释//睡眠(1000),则只会收到B和D.

任何想法为什么发生这种情况? 没有睡眠的服务器输出如下:

  GetOverlappedResult 0 success 1 state 0 GetLastErr or 997 Error: 997 Error IO is still pending GetOverlappedResult 1 success 1 state 0 GetLastErr or 997 Message B GetOverlappedResult 1 success 1 state 1 GetLastErr or 997 Message C GetOverlappedResult 1 success 1 state 1 GetLastErr or 997 Message D GetOverlappedResult 1 success 1 state 1 GetLastErr or 997 Error: 997 Error IO is still pending 

在服务器的读取循环中,您将丢弃任何异步到达的数据。

在GetOverlappedResult()已经报告了待处理的I / O操作完成之后,缓冲区包含来自该操作的数据。 您将忽略该数据,并向同一缓冲区发出新的读取操作。

得到任何消息的唯一原因是(在大多数运行中),所有四条消息将同时写入管道的内部缓冲区。 第一条消息异步到达,所以你错过了,但其余的三条消息已经在管道中,所以这些读取可以立即完成。