我试图找出我的程序冻结的原因,并将其范围缩小到 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;
}
}
}