为啥对 recv 的重叠调用会返回 ERROR_NO_MORE_ITEMS(259)?

Posted

技术标签:

【中文标题】为啥对 recv 的重叠调用会返回 ERROR_NO_MORE_ITEMS(259)?【英文标题】:Why would an Overlapped call to recv return ERROR_NO_MORE_ITEMS(259)?为什么对 recv 的重叠调用会返回 ERROR_NO_MORE_ITEMS(259)? 【发布时间】:2011-09-30 14:04:03 【问题描述】:

我使用 I/O 完成端口和 winsock 套接字进行了一些测试。 我遇到过,有时在我从连接接收数据然后在该套接字上再次相邻调用 WSARecv 后,它会立即返回错误 259 (ERROR_NO_MORE_ITEMS)。

我想知道为什么系统用这个错误标记重叠事务,而不是让 recv 调用阻塞/等待传入数据。

你知道这是什么意思吗?

我很高兴听到你的想法。

编辑:代码

do
    
        OVERLAPPED* pOverlapped = nullptr;
        DWORD dwBytes = 0; ULONG_PTR ulKey = 0;

        //Dequeue a completion packet
        if(!m_pIOCP->GetCompletionStatus(&dwBytes, &ulKey, &pOverlapped, INFINITE))
            DebugBreak();

        //Evaluate
        switch(((MYOVERLAPPED*)pOverlapped)->WorkType)
        
        case ACCEPT_OVERLAPPED_TYPE:
            
                //cast
                ACCEPT_OVERLAPPED* pAccept = (ACCEPT_OVERLAPPED*)pOverlapped;

                //Associate the newly accepted connection with the IOCP
                if(!m_pIOCP->AssociateHandle((HANDLE)(pAccept->pSockClient)->operator SOCKET(), 1))
                
                    //Association failed: close the socket and and delte the overlapped strucuture

                

                //Call recv
                RECV_OVERLAPPED* pRecvAction = new RECV_OVERLAPPED;
                pRecvAction->pSockClient = pAccept->pSockClient;
                short s = (pRecvAction->pSockClient)->Recv(pRecvAction->strBuf, pRecvAction->pWSABuf, 10, pRecvAction);
                if(s == Inc::REMOTECONNECTION_CLOSED)
                
                    //Error stuff
                


                //Call accept again (create a new ACCEPT_OVERLAPPED to ensure overlapped being zeroed out)
                ACCEPT_OVERLAPPED *pNewAccept = new ACCEPT_OVERLAPPED;
                pNewAccept->pSockListen = pAccept->pSockListen;
                pNewAccept->pSockClient = new Inc::CSocket((pNewAccept->pSockListen)->Accept(nullptr, nullptr, pNewAccept));

                //delete the old overlapped struct
                delete pAccept;
            
            break;
        case RECV_OVERLAPPED_TYPE:
            
                RECV_OVERLAPPED* pOldRecvAction = (RECV_OVERLAPPED*)pOverlapped;
                if(!pOldRecvAction->InternalHigh)
                
                    //Connection has been closed: delete the socket(implicitly closes the socket)
                    Inc::CSocket::freewsabuf(pOldRecvAction->pWSABuf);      //free the wsabuf
                    delete pOldRecvAction->pSockClient;
                
                else
                
                    //Call recv again (create a new RECV_OVERLAPPED)
                    RECV_OVERLAPPED* pNewRecvAction = new RECV_OVERLAPPED;
                    pNewRecvAction->pSockClient = pOldRecvAction->pSockClient;
                    short sRet2 = (pNewRecvAction->pSockClient)->Recv(pNewRecvAction->strBuf, pNewRecvAction->pWSABuf, 10, pNewRecvAction);



                    //Free the old wsabuf
                    Inc::CSocket::freewsabuf(pOldRecvAction->pWSABuf);
                    delete pOldRecvAction;

                

减少错误检查...

Recv-member-function 是 WSARecv-call 的简单包装器,它创建 WSABUF 和接收缓冲区本身(需要用户通过 freewsabuf 清理 - 只是提一下)...

【问题讨论】:

没什么意义,没什么可看的。请注意,等待肯定不能保证,重叠的调用可以立即完成。 你需要展示一些代码,最好是一个最小的可编译示例。请注意,即使您将重叠结构传递给 API 函数,操作仍然可以同步完成。 另外,您是否使用 WSAGetLastError(而不是 GetLastError)? @Avakar WSAGetLastError 返回 0(无错误/成功) 【参考方案1】:

看起来我发送的数据少于接收方请求的数据。 但由于它是一个重叠操作,通过 TCP 连接接收一小部分请求的垃圾会触发完成指示,并显示错误 ERROR_NO_MORE_ITEMS,这意味着没有什么比它已经拥有的要接收的了。

【讨论】:

以上是关于为啥对 recv 的重叠调用会返回 ERROR_NO_MORE_ITEMS(259)?的主要内容,如果未能解决你的问题,请参考以下文章

为啥处理字节的 Windows API 调用(例如“recv”)使用默认签名的 char*?

为啥 client.recv(1024) 在这个简单的 WebSocket 服务器实现中返回一个空字节文字?

为啥 sys socket recv 函数不填充数据但返回字节长度?

为啥在服务器端和客户端调用 recv 和 send 函数时都使用客户端的文件描述符?

为啥对部署到服务器的服务的调用不返回问题详细信息对象?

C++ 套接字 recv() 系统调用返回 -1