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

发布于 2024-12-07 16:48:40 字数 3204 浏览 0 评论 0原文

我使用 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 清理 - 仅提及) ...

I did a few tests with an I/O-Completion port and winsock sockets.
I encountered, that sometimes after I received data from a connection and then adjacently call WSARecv again on that socket it returns immediately with the error 259 (ERROR_NO_MORE_ITEMS).

I am wondering why the system flags the overlapped transaction with this error instead of keeping the recv call blocking/waiting for incoming data.

Do You know what´s the sense of this ?

I would be glad to hear about your thoughts.

Edit: Code

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;

                }

Cutted error checkings...

The Recv-member-function is a simple wrapper around the WSARecv-call which creates the WSABUF and the receiving buffer itself (which needs to be cleaned up by the user via freewsabuf - just to mention)...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梨涡 2024-12-14 16:48:40

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

It looks like I was sending less data than was requested by the receiving side.
But since it´s an overlapped operation receiving a small junk of the requested bunch via the TCP-connection would trigger the completion indication with the error ERROR_NO_MORE_ITEMS, meaning there was nothing more to recv than what it already had.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文