У нас есть поток, считывающий сокет.Мы столкнулись с проблемой в сети с немного большей задержкой, к которой мы привыкли, когда наш цикл чтения, по-видимому, перестал бы получать уведомления о событиях чтения в сокете.Исходный код (некоторые проверки ошибок удалены):
HANDLE hEventSocket = WSACreateEvent();
WSAEventSelect(pIOParams->sock, hEventSocket, FD_READ | FD_CLOSE);
std::array<HANDLE, 2> ahEvents;
// This is an event handle that can be called from another thread to
// get this read thread to exit
ahEvents[0] = pIOParams->hEventStop;
ahEvents[1] = hEventSocket;
while(pIOParams->bIsReading)
{
// wait for stop or I/O events
DWORD dwTimeout = 30000; // in ms
dwWaitResult = WSAWaitForMultipleEvents(ahEvents.size(), ahEvents.data(), FALSE, dwTimeout, FALSE);
if(dwWaitResult == WSA_WAIT_TIMEOUT)
{
CLogger::LogPrintf(LogLevel::LOG_DEBUG, "CSessionClient", "WSAWaitForMultipleEvents time out");
continue;
}
if(dwWaitResult == WAIT_OBJECT_0) // check to see if we were signaled to stop from another thread
{
break;
}
if(dwWaitResult == WAIT_OBJECT_0 +1)
{
// determine which I/O operation triggered event
if (WSAEnumNetworkEvents(pIOParams->sock, hEventSocket, &NetworkEvents) != 0)
{
int err = WSAGetLastError();
CLogger::LogPrintf(LogLevel::LOG_WARN, "CSessionClient", "WSAEnumNetworkEvents failed (%d)", err);
break;
}
// HERE IS THE LINE WE REMOVED THAT SEEMED TO FIX THE PROBLEM
WSAResetEvent(hEventSocket);
// Handle events on socket
if (NetworkEvents.lNetworkEvents & FD_READ)
{
// Do stuff to read from socket
}
if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
// Handle that the socket was closed
break;
}
}
}
Вот проблема: с кодом WSAResetEvent(hEventSocket);
иногда программа работает и читает все данные с сервера, но иногда кажется,чтобы застрять в цикле получения WSA_WAIT_TIMEOUT, даже если на сервере, похоже, имеются данные, поставленные в очередь для него.
Пока программа выполняет цикл приема WSA_WAIT_TIMEOUT, Process Hacker
показывает сокет, подключенный в нормальном состоянии.
Теперь мы знаем, что WSAEnumNetworkEvents
сбросит hEventSocket, но не похоже, что дополнительный вызов WSAResetEvent
должен повредить.Также не имеет смысла, что это постоянно портит сигнализацию.Я ожидаю, что, возможно, мы не получим уведомление о последнем фрагменте данных для чтения, так как данные могли быть прочитаны между вызовами WSAEnumNetworkEvents
и WSAResetEvent
, но я предполагаю, что, как только дополнительные данные поступятв сокете hEventSocket
будет поднят.
Странной частью этого является то, что мы выполняем этот код в течение многих лет, и мы только сейчас видим эту проблему.
Есть идеи, почему это может вызвать проблемы?