WinSock2.2 перестает отвечать, когда я выполняю операции на диске

Я написал класс сокетов на C ++, дизайн основан на событиях, это означает, что каждые 64 игрока будут создавать новый поток для обработки этих сокетов. Моя проблема в том, что когда я начинаю читать файл, или писать, или даже копировать и вставлять, он говорит: «Server.exe не отвечает», а когда процесс завершается (диск), он начинает отвечать снова, отключая некоторые проигрыватели в моем сервер.

Вот мой слушатель:

void ServerSocket::ListenerThread(ServerSocket * Server)
{
// Inicializa a lista de espera.
InitializeCriticalSection(&Server->m_EventCheckers.Lock);
InitializeCriticalSection(&Server->m_Pending.Lock);

bool TerminateThread = false;
DWORD Result = 0;
WSANETWORKEVENTS NetEvents = { 0 };
// Enquanto for permitida a leitura de novas conexões.
while (WaitForSingleObject(Server->m_Listener.WaitObject, FALSE) != WAIT_OBJECT_0)
{
Result = WSAWaitForMultipleEvents(1, &Server->m_Listener.Event, FALSE, 2500, FALSE);
if (Result == WSA_WAIT_EVENT_0)
{
// Existe algo pendente no soquete.
// Enumera os eventos pendentes.
Result = WSAEnumNetworkEvents(Server->m_Listener.Socket, Server->m_Listener.Event, &NetEvents);
if (Result != SOCKET_ERROR)
{
// Verifica qual evento está ativo.
if (NetEvents.lNetworkEvents & FD_ACCEPT)
{
INT ErrorCode = NetEvents.iErrorCode[FD_ACCEPT_BIT];
if (ErrorCode == NULL)
{
// Aceita uma nova conexão.
Client* User = new Client();
if (User->AcceptFromSocket(Server->m_Listener.Socket))
{
int LastUserCount;

// Coloca na lista de espera e verifica as procedures.
EnterCriticalSection(&Server->m_Pending.Lock);
LastUserCount = Server->m_ConnectionCount++;
Server->m_Pending.Clients.push_front(User);
LastUserCount += Server->m_Pending.Clients.size();
LeaveCriticalSection(&Server->m_Pending.Lock);

EnterCriticalSection(&Server->m_EventCheckers.Lock);
if (Server->m_EventCheckers.Runnings.size() * WSA_MAXIMUM_WAIT_EVENTS < LastUserCount)
{
std::shared_ptr<ThreadInformation> Information = std::make_shared<ThreadInformation>();
Information->EventObject = CreateEventA(NULL, TRUE, FALSE, NULL);
Information->Thread.Initialize(std::thread(EventChecker, Server, Information));
Server->m_EventCheckers.Runnings.push_back(Information);

char szMessage[256] = { 0 };
sprintf_s(szMessage, "Número de Threads( %d ) -> Jogadores( %d )",
Server->m_EventCheckers.Runnings.size(), LastUserCount);

World::ServerManager->LogFile("Socket", szMessage);

}
LeaveCriticalSection(&Server->m_EventCheckers.Lock);
}
else
{
// Algum erro ocorreu durante o accept.
delete User;
}
}
else
{
// Fecha a escuta.
SetEvent(Server->m_Listener.WaitObject);
TerminateThread = true;
}
}
else if (NetEvents.lNetworkEvents & FD_CLOSE)
{
INT ErrorCode = NetEvents.iErrorCode[FD_CLOSE_BIT];
if (ErrorCode == NULL)
{
// Fecha a escuta.
SetEvent(Server->m_Listener.WaitObject);
TerminateThread = true;
}
else
{
// Fecha a escuta.
SetEvent(Server->m_Listener.WaitObject);
TerminateThread = true;
}
}
}
else
{
// Fecha a escuta.
SetEvent(Server->m_Listener.WaitObject);
TerminateThread = true;
}
}
else if (Result != WSA_WAIT_TIMEOUT)
{
// Fecha a escuta.
SetEvent(Server->m_Listener.WaitObject);
TerminateThread = true;
}
}

if (TerminateThread)
{
Server->m_Listener.WaitObject = INVALID_HANDLE_VALUE;
WSACloseEvent(Server->m_Listener.Event);
closesocket(Server->m_Listener.Socket);

Log("Function: ServerSocket::ListenerThread(). Details: TerminateThread is true.\n");
}

// Deleta a lista de espera.
DeleteCriticalSection(&Server->m_Pending.Lock);
DeleteCriticalSection(&Server->m_EventCheckers.Lock);
}

И вот где я обращаюсь с сокетом.

void ServerSocket::EventChecker(ServerSocket * Server, std::shared_ptr<ThreadInformation> Information)
{
SOCKET Sockets[WSA_MAXIMUM_WAIT_EVENTS] = { INVALID_SOCKET };
WSAEVENT Events[WSA_MAXIMUM_WAIT_EVENTS] = { WSA_INVALID_EVENT };

DWORD LastConnection = GetCurrentTime();
DWORD LastUserCheck = NULL;
DWORD Result = NULL;

WSANETWORKEVENTS NetworkEvents = { 0 };
std::vector<std::shared_ptr<Client>> Clients;

// Predicate to Erase-Remove Idiom.
auto UserPredicate = [&](std::shared_ptr<Client> User)
{
if (!User || User->GetSocket() == INVALID_SOCKET || User->GetEvent() == WSA_INVALID_EVENT || User->GetFreeFlag())
return true;

return false;
};

while (WaitForSingleObject(Information->EventObject, FALSE) != WAIT_OBJECT_0)
{
// Se não tiver clientes conectados, sai da thread para economizar CPU.
if (Clients.empty() && GetCurrentTime() - LastConnection > 150)
{
SetEvent(Information->EventObject);
continue;
}

// Verifica se esta na hora de pegar os usuários na lista de espera.
if (LastUserCheck + 2000 < GetCurrentTime() && Clients.size() < WSA_MAXIMUM_WAIT_EVENTS)
{
// Possui algum usuário na lista de espera.
EnterCriticalSection(&Server->m_Pending.Lock);

// Obtêm o usuário da lista.
for (size_t i = 0; i < Server->m_Pending.Clients.size(); i++)
{
if (Clients.size() < WSA_MAXIMUM_WAIT_EVENTS)
{
Client * User = Server->m_Pending.Clients.back();
if (User)
{
// Obtêm o ownership do usuário com um ponteiro compartilhado.
Clients.push_back(std::move(std::shared_ptr<Client>(User)));

Server->m_Pending.Clients.pop_back();
}
}
else
break;
}

LeaveCriticalSection(&Server->m_Pending.Lock);

LastUserCheck = GetCurrentTime();
}

// Verifica por conexões não autenticadas.
for (int i = 0; i < (int)Clients.size(); i++)
{
if (!Clients[i]->isInitialized() && !Clients[i]->GetPlayerData())
{
if (Clients[i]->GetLastRecvTime() + Connection::MaxAutorizationTime < GetCurrentTime())
{
// Percorre todos os jogadores para desconectar o IP.
for (int c = 0; c < (int)Clients.size(); c++)
{
if (_strcmpi(Clients[i]->GetIP(), Clients[c]->GetIP()) == 0)
{
Clients[c]->CloseSocket();
}
}
}
}
}

// Verifica por conexões inválidas de time-out.
for (int i = 0; i < (int)Clients.size(); i++)
{
if (Clients[i]->GetLastRecvTime() + (60 * 1000) < GetCurrentTime())
{
if (!Clients[i]->isReceivingUpdate())
{
Clients[i]->CloseSocket();
}
}
}

// Verifica por eventos inválidos ou jogadores "recém desconectados".
Clients.erase(std::remove_if(Clients.begin(), Clients.end(), UserPredicate), Clients.end());

// Separa os eventos e os soquetes.
for (unsigned i = 0; i < Clients.size(); i++)
{
Sockets[i] = Clients[i]->GetSocket();
Events[i] = Clients[i]->GetEvent();
}

// Caso não exista um usuário, apenas continua o loop.
if (Clients.empty())
continue;

LastConnection = GetCurrentTime();
Result = WSAWaitForMultipleEvents(Clients.size(), Events, FALSE, 1000, FALSE);
if (Result != SOCKET_ERROR)
{
if (Result >= WSA_WAIT_EVENT_0 && Result < WSA_MAXIMUM_WAIT_EVENTS + WSA_WAIT_EVENT_0)
{
INT Index = Result - WSA_WAIT_EVENT_0;
if (Clients.size() >= 0 && Index < int(Clients.size()))
{
std::shared_ptr<Client> & User = Clients[Index];

Result = WSAEnumNetworkEvents(User->GetSocket(), User->GetEvent(), &NetworkEvents);
if (Result != SOCKET_ERROR)
{
INT ErrorCode = 0;
if (NetworkEvents.lNetworkEvents & FD_READ)
{
ErrorCode = NetworkEvents.iErrorCode[FD_READ_BIT];
if (ErrorCode == FALSE)
{
// O soquete está com dados pendentes.
char DataReceived[Connection::MAX_BufferSize] = { 0 };
int Len = recv(User->GetSocket(), DataReceived, sizeof(DataReceived), NULL);
if (Len > 0)
{
if (User->isFirstRecv())
{
if (Len >= 4)
{
User->Initialize();
}
else
{
Clients.erase(Clients.begin() + Index);
continue;
}
}

if (!User->PushRecv(DataReceived, Len))
{
Clients.erase(Clients.begin() + Index);
continue;
}
}
else
{
Clients.erase(Clients.begin() + Index);
}
}
else
{
Log("Function: ServerSocket::RunSocketProcedure(). Details: FD_ReadBit is %d.\n", ErrorCode);
Server->AddLostConnection(Clients[Index]);
Clients.erase(Clients.begin() + Index);
continue;
}
}
else if (NetworkEvents.lNetworkEvents & FD_WRITE)
{
ErrorCode = NetworkEvents.iErrorCode[FD_WRITE_BIT];
if (ErrorCode == FALSE)
{
// O soquete está livre para mandar dados.
User->WriteData();
}
else
{
Log("Function: ServerSocket::RunSocketProcedure(). Details: FD_WriteBit is %d.\n", ErrorCode);
Server->AddLostConnection(Clients[Index]);
Clients.erase(Clients.begin() + Index);
continue;
}
}
else if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
ErrorCode = NetworkEvents.iErrorCode[FD_CLOSE_BIT];
if (ErrorCode == FALSE)
{
User->GracefulShutdown();
Clients.erase(Clients.begin() + Index);
continue;
}
else
{
Log("Function: ServerSocket::RunSocketProcedure(). Details: FD_CloseBit is %d.\n", ErrorCode);
Server->AddLostConnection(Clients[Index]);
Clients.erase(Clients.begin() + Index);
continue;
}
}
}
else
{
Log("Function: ServerSocket::RunSocketProcedure(). Details: Network ErrorCode is %d.\n", WSAGetLastError());
Server->AddLostConnection(Clients[Index]);
Clients.erase(Clients.begin() + Index);
continue;
}
}
}
}
else if (Result != WSA_WAIT_TIMEOUT)
{
char szMessage[256] = { 0 };
sprintf_s(szMessage, "WSAWaitForMultipleEvents Error Code [ %d ]", Result);
World::ServerManager->LogFile("Socket", szMessage);
Sleep(100);
}
}

EnterCriticalSection(&Server->m_EventCheckers.Lock);

Information->EventObject = INVALID_HANDLE_VALUE;

for (unsigned i = 0; i < Server->m_EventCheckers.Runnings.size(); i++)
{
if (Server->m_EventCheckers.Runnings[i] == Information)
{
Server->m_EventCheckers.Runnings.erase(Server->m_EventCheckers.Runnings.begin() + i);
break;
}
}

LeaveCriticalSection(&Server->m_EventCheckers.Lock);
}

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector