我想实现一个服务器/客户端使用命名管道(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()仍然返回一个待处理的操作(这是"ReadFile2: ERROR_IO_PENDING"错误消息后的最后一个"msg"输出)
我的循环错了吗?我是否滥用ReadFile()/GetQueuedCompletionStatus() ?
谢谢
你的写作相关功能在哪里?看来你的代码顺序不对。在_read_data_cb
例程中,应该首先调用GetQueuedCompletionStatus
,然后根据lpOverlapped
参数,接收到的数据应该在ReadFile函数中指定的缓冲区中准备好。由于调用Readfile时没有检查OVERLAPPED
是否是send上下文或recv上下文的重叠结构,因此没有得到预期的输出。下面的代码应该可以解决问题:
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)
}
...