【发布时间】:2020-02-25 17:01:27
【问题描述】:
我继承了一些Windows TCP服务器代码,却发现它不起作用。
我打电话给GetQueuedCompletionStatus(),这会产生ERROR_CONNECTION_ABORTED 错误。
调用它的代码:
unsigned int WinTCPServer::runWorker()
{
unsigned int returnValue = 0U;
bool bStayAlive = true;
while (bStayAlive)
{
// Wait for IOCP events.
DWORD bytesTransferred = 0U;
ULONG_PTR completionKey = 0U;
LPOVERLAPPED pOverlapped = NULL;
BOOL bResult = GetQueuedCompletionStatus(_hIOCP, &bytesTransferred, &completionKey, &pOverlapped, INFINITE);
if (FALSE == bResult)
{
// If pOverlapped == NULL then no packet was dequeued, the other parameters contain
// undefined values, and we can't tell which socket it was. If pOverlapped != NULL,
// the function has dequeued a failed completion packet.
if (pOverlapped == NULL)
{
std::string error = "GetQueuedCompletionStatus failed, unknown context, interface id: " + std::to_string(_interfaceID);
_consoleLog.AppError(__FILE__, __LINE__, error);
}
else
{
// If the completion key is zero, this was a shut-down post that failed
// (PostQueuedCompletionStatus with zero). This shouldn't happen! No real
// way of handling this gracefully.
if (0U == completionKey)
{
_consoleLog.PlatformError(__FILE__, __LINE__, "GetQueuedCompletionStatus failed", GetLastError());
std::string error = "TCP server shut down error, interface ID " + std::to_string(_interfaceID);
_consoleLog.AppError(__FILE__, __LINE__, error);
}
else
{
// Don't report client disconnections as errors.
DWORD lastError = GetLastError();
if ((ERROR_NETNAME_DELETED != lastError) && (ERROR_OPERATION_ABORTED != lastError))
{
_consoleLog.PlatformError(__FILE__, __LINE__, "GetQueuedCompletionStatus failed", lastError);
}
// Perform any outstanding actions on the overlapped operation.
WinTCPClientContext* pClientContext = reinterpret_cast<WinTCPClientContext*>(completionKey);
pClientContext->ProcessIncompleteOverlapped(pOverlapped);
// We don't want to use this client any more.
removeClient(*pClientContext);
}
}
}
else
{
// A null client context means the server is shutting down (i.e. has called
// PostQueuedCompletionStatus with a NULL value).
if (0U == completionKey)
{
bStayAlive = false;
}
else
{
// Convert the completion key into the client context.
WinTCPClientContext* pClientContext = reinterpret_cast<WinTCPClientContext*>(completionKey);
if (0U == bytesTransferred)
{
// This means a gracefull disconnection of the client.
// We should get this for every outstanding post (i.e.
// outstanding reads and writes).
pClientContext->ProcessIncompleteOverlapped(pOverlapped);
// We don't want to use this client any more.
removeClient(*pClientContext);
}
else
{
// Process the overlapped result
try
{
// Process the post.
pClientContext->ProcessOverlapped(pOverlapped, bytesTransferred);
}
catch (utility::CommsException& ex)
{
_consoleLog.PlatformError(ex.Filename(), ex.Line(), ex.Error(), ex.ErrorCode());
_consoleLog.StatusInfo(__FILE__, __LINE__, "client error, disconnecting");
// We don't want to use this client any more.
removeClient(*pClientContext);
}
catch (utility::Exception& ex)
{
_consoleLog.AppError(ex.Filename(), ex.Line(), ex.Error());
_consoleLog.StatusInfo(__FILE__, __LINE__, "client error, disconnecting");
// We don't want to use this client any more.
removeClient(*pClientContext);
}
}
}
}
}
return returnValue;
}
服务器连接到客户端,并且两者之间的一些消息被正确处理。但是,有几条消息会导致此错误,我不知道为什么。
这个错误的原因是什么,如何调试?
【问题讨论】:
-
起初你不检查
bResult- 如果它是真的 -GetLastError()在这里没有意义。如果bResult为假-这是实际错误,但GetQueuedCompletionStatus与此无关-您只需获得某些I/O 操作的最终状态。什么操作 - 你不显示,根据你的信息不可能说一些具体的东西 -
我已编辑问题以提供更多上下文
-
这是真正的代码?!例如,当
bResult为真时,您如何处理案例?反正只是通过一些代码sn-p不可能在这里发现问题 -
我现在已经包含了 while 函数