我试着找出我的程序冻结的原因,并将其缩小到GetQueuedCompletionStatus()。
所有IOCP线程都被冻结,线程唯一的阻塞调用是GetQueuedCompletionStatus()。
有没有理由说GetQueuedCompletionStatus()会在大约30分钟~6小时的运行时间后永远阻塞,即使还有客户连接到相关的套接字?
这是一个使用IOCP的TCP Winsock程序。 操作系统是Windows Server 2008 R2 Enterprise。
感谢。
线程代码:
while (TRUE)
{
pClient = NULL;
pOverlapped = NULL;
bRet = GetQueuedCompletionStatus(hCompletionPort, &dwIOLen, (LPDWORD)&pClient, (LPOVERLAPPED*)&pOverlapped, INFINITE);
if (bRet == true && pClient != NULL && pOverlapped != NULL && pClient->bConnected == true && pClient->bToDisconnect == false)
{
if (pOverlapped->bIOMode == 0) // Recv
{
if (TryEnterCriticalSection(&pClient->mNetworkReadCSection))
{
pClient->dwSockBuffLength += dwIOLen;
// Packet processing here...
WSABUF pWSABuf;
pWSABuf.buf = (char*)&pClient->mSockBuffer[pClient->dwSockBuffLength];
pWSABuf.len = 10000 - pClient->dwSockBuffLength;
DWORD dwRecvd;
DWORD dwFlags = 0;
memset(&pClient->mSockOverlapped, 0x00, sizeof(WSAOVERLAPPED));
pClient->mSockOverlapped.bIOMode = 0;
int iSent = WSARecv(pClient->ClientSocket, &pWSABuf, 1, &dwRecvd, &dwFlags, (WSAOVERLAPPED*)&pClient->mSockOverlapped, NULL);
if (iSent == SOCKET_ERROR)
{
if (WSAGetLastError() == 10053 || WSAGetLastError() == 10054 || WSAGetLastError() == 10058)
{
//pClient->bToDisconnect = true;
//LeaveCriticalSection(&pClient->mNetworkReadCSection);
OnDissconnect(pPacketWriter, pClient->iClientID);
continue;
}
if (WSAGetLastError() != 997 && WSAGetLastError() != 10004 && WSAGetLastError() != 10038)
WriteToFile("IOCPSocketErr.txt", "[%s] Socket Error: %d\n", pClient->szPlayerName, WSAGetLastError());
}
LeaveCriticalSection(&pClient->mNetworkReadCSection);
}
else
{
PostQueuedCompletionStatus(hCompletionPort, dwIOLen, (DWORD)pClient, (OVERLAPPED*)pOverlapped);
}
}
else if (pOverlapped->bIOMode == 1) // Send
{
dwBytesSent += dwIOLen;
}
}
}
答案 0 :(得分:2)
这很可能是您代码中的错误。
我已经与IOCP和GetQueuedCompletionStatus()
合作了10多年了,我从来没有在任何平台上看到它的问题。
首先,断开连接上方注释掉的LeaveCriticalSection(&pClient->mNetworkReadCSection);
会在发生此错误后将套接字锁定...
我个人更喜欢看到使用的错误常数而不是魔术数字,我很难确切地看到你在这里“处理”了哪些错误。
我希望您最终处于没有待处理的I / O操作的情况下,因此您的IOCP线程没有任何活动。您可以维护一个用于调试目的的计数器,当您发出I / O操作时它会递增,当它完成时递减,当您将自己的完成发布到端口时也会递增。这样可以帮助您查看在进入挂起的程序时是否有任何待处理的I / O操作。请记住在发出操作之前递增计数器(如果操作失败则递减计数器)而不是在之后发出计数器,否则如果在递增之前完成,计数器可能会变为负数。
答案 1 :(得分:0)
如果我正确阅读文档,您可能会遇到GetQueuedCompletionStatus返回false并且pOverlapped不为NULL的情况。也许你应该测试并处理这种情况。