为什么对recv的Overlapped调用返回ERROR_NO_MORE_ITEMS(259) ?

Why would an Overlapped call to recv return ERROR_NO_MORE_ITEMS(259)?

本文关键字:MORE NO ITEMS ERROR recv Overlapped 返回 调用 为什么      更新时间:2023-10-16

我用I/O-Completion端口和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清理-只是提一下)…

看起来我发送的数据比接收方请求的少。但是由于它是一个重叠的操作,通过tcp连接接收一小部分请求的垃圾,将触发带有ERROR_NO_MORE_ITEMS错误的完成指示,这意味着除了它已经拥有的东西之外没有更多的东西要接收。