为啥对 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 函数不填充数据但返回字节长度?