Почему перекрывающийся вызов recv возвращает ERROR_NO_MORE_ITEMS (259)? - PullRequest
0 голосов
/ 30 сентября 2011

Я провел несколько тестов с портом 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, которая создает WSABUF и сам приемный буфер (который должен быть очищен пользователем через freewsabuf - просто упомянуть) ...

1 Ответ

0 голосов
/ 03 октября 2011

Похоже, что я отправлял меньше данных, чем было запрошено принимающей стороной. Но так как это перекрывающаяся операция, получающая небольшой мусор запрошенной связки через TCP-соединение, это вызвало бы индикацию завершения с ошибкой ERROR_NO_MORE_ITEMS, означая, что нет ничего больше, чем то, что у него уже было.

...