Winapi 我的循环错了吗?我是否误用了ReadFile()和I/O完成端口?

Winapi 我的循环错了吗?我是否误用了ReadFile()和I/O完成端口?,winapi,readfile,io-completion-ports,Winapi,Readfile,Io Completion Ports,我想使用命名管道(用于IPC)实现服务器/客户机。我使用异步(重叠)连接和I/O完成端口(我搜索了很多,似乎这是最有效的方法) 首先,代码如下: 服务器: 客户: 问题在于服务器(我可以改进客户端,但在服务器工作时我会这样做) 我使用这样的I/O完成端口:基本上,我运行一个调用ReadFile()的线程。如果返回TRUE,则获取所有数据;如果返回FALSE,且错误为error\u IO\u PENDING,则使用GetQueuedCompletionStatus()等待 奇怪的是,即使我读取了所

我想使用命名管道(用于IPC)实现服务器/客户机。我使用异步(重叠)连接和I/O完成端口(我搜索了很多,似乎这是最有效的方法)

首先,代码如下:

服务器:

客户:

问题在于服务器(我可以改进客户端,但在服务器工作时我会这样做)

我使用这样的I/O完成端口:基本上,我运行一个调用ReadFile()的线程。如果返回TRUE,则获取所有数据;如果返回FALSE,且错误为error\u IO\u PENDING,则使用GetQueuedCompletionStatus()等待

奇怪的是,即使我读取了所有数据,最后一个ReadFile()调用也失败了,错误是error\u IO\u PENDING

我调用ReadFile()的线程是服务器代码第64行的开头

客户端发送24个字节(字符串“sallt,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\u IO\u pending”错误消息)

我的循环错了吗?我是否误用了ReadFile()/GetQueuedCompletionStatus()


谢谢

您的写相关功能在哪里?看来你的代码顺序不对。在
\u read\u data\u 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)
}
...
while(TRUE)
{
bReturnValue=GetQueuedCompletionStatus(pIOCPServer->m_pIOCP,&DWBYTESTTransfered,(DWORD*)pClient,reinterpret_cast(&pOverlapped),无限);
如果(!bReturnValue)
{
if(NULL==pOverlapped)
继续;
其他的
打破
}
其他的
{
if(pOverlapped==NULL)
继续;
}
if(dwByTestTransferred==0)
打破
if(lpOverlapped==&(pClient->m_pRecvContext->overlapped))
pClient->handleRecvEvent(dwbytesttransfered)
else if(lpOverlapped==&(pClient->m_pSendContext->overlapped))
pClient->handleSendEvent(DwByTestTransferred)
}
...

写相关函数在哪里?看来你的代码顺序不对。在
\u read\u data\u 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)
}
...
while(TRUE)
{
bReturnValue=GetQueuedCompletionStatus(pIOCPServer->m_pIOCP,&DWBYTESTTransfered,(DWORD*)pClient,reinterpret_cast(&pOverlapped),无限);
如果(!bReturnValue)
{
if(NULL==pOverlapped)
继续;
其他的
打破
}
其他的
{
if(pOverlapped==NULL)
继续;
}
if(dwByTestTransferred==0)
打破
if(lpOverlapped==&(pClient->m_pRecvContext->overlapped))
pClient->handleRecvEvent(dwbytesttransfered)
else if(lpOverlapped==&(pClient->m_pSendContext->overlapped))
pClient->handleSendEvent(DwByTestTransferred)
}
...

问题似乎在于管道的模式。我必须使用消息模式(客户端和服务器),但它没有帮助:第一个ReadFile()调用失败,读取字节数为0,错误为error\u MORE\u DATA。虽然出现这种错误是正常的,但前5个字节存储在哪里?问题似乎是管道的模式。我必须使用消息模式(客户端和服务器),但它没有帮助:第一个ReadFile()调用失败,读取字节数为0,错误为error\u MORE\u DATA。虽然出现这种错误是正常的,但前5个字节存储在哪里?