Невозможность коннекта к серверу
От:
sterx555
Дата: 20.08.04 08:23
Оценка:
Ситуация такая:
Существует сервер и клиенты. До какого-то часа х все работает прекрасно: клиенты присоединяются, сервер начинает отправлять им данные.
Наступает час х (несколько дней а то и месяцы видимо в зависимости от активности клиентов) и клиент1 не может присоединиться к серверу.
Если при этом какой-то клиент2, имеющий в данный момент соединение с сервером отсоединится, то клиент1 тут же установит соединение. Ощущение такое что не все соединения с сервером завершены и продолжают висеть неявным образом, хотя closesocket была вызвана для всех (в этом я уверен, поскольку иначе клиенты для которых на стророне сервера не вызвана closesocket были бы видны в окне текущих соединений сервера. код написан таким образом, что из окна текущих соединений клиент удаляется только после вызова closesocket).
Вопрос как я ламер такого мог добиться? Что можно предположить в теории?
UINT CClientSocketServer::ClientARMThread(LPVOID pParam)
//трид по обслуживанию клиента АРМ
//прием и передача данных по каналу TCP|IP
{
CClientARMConnection *pNewConn = (CClientARMConnection*)pParam;
CClientSocketServer *pClientSocketServer = pNewConn->m_pClientSocketServer;
SOCKET s = pNewConn->m_socket;
CMsgClient *&pMsgClient = pNewConn->m_pMsg;
int result;
WSAEVENT EventArray[5];
WSANETWORKEVENTS NetworkEvents;
WSAEVENT Event = WSACreateEvent();
long m_lenReceive = 0;
long m_seekReceive = 0;
char szBufferCaption[ MinLengthMessage ];
int seekCaption = 0;
BYTE *pbDataRead = NULL;
if(Event == WSA_INVALID_EVENT)
{
TRACE("WSACreateEvent(...) failure ClientThread\n");
pClientSocketServer->CleanupThread(NULL, s, pNewConn, GetCurrentThreadId(), pbDataRead );
return THREADEXIT_SUCCESS;
}
result = WSAEventSelect( s, Event, FD_READ | FD_CLOSE );
if(result == SOCKET_ERROR)
{
TRACE("WSAEventSelect(...) failure ClientThread\n");
pClientSocketServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId(), pbDataRead );
return THREADEXIT_SUCCESS;
}
EventArray[0] = pNewConn->m_pEventClose->m_hObject;
EventArray[1] = pClientSocketServer->m_pEventShutdown->m_hObject;
EventArray[2] = Event;
EventArray[3] = pNewConn->m_pEventNewMsg->m_hObject;
EventArray[4] = pNewConn->m_pEventNewMsgSys->m_hObject;
CoInitialize( NULL );
for(;)
{
DWORD EventCaused = WSAWaitForMultipleEvents(
5,
EventArray,
FALSE,
WSA_INFINITE,
FALSE);
if(WSA_WAIT_FAILED == EventCaused)
{
TRACE("WSAWaitForMultipleEvents(...) failure ClientThread\n");
pClientSocketServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId(), pbDataRead );
CoUninitialize( );
return THREADEXIT_SUCCESS;
}
//
// Check if our Server mission is over or Client established connection, but no request so far
//
if( EventCaused == 0 || EventCaused == 1 || EventCaused == WSA_WAIT_TIMEOUT)
{
pClientSocketServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId(), pbDataRead );
CoUninitialize( );
return THREADEXIT_SUCCESS;
}
//
// Determine which network event occured
//
result = WSAEnumNetworkEvents(
s,
Event,
&NetworkEvents);
if(result == SOCKET_ERROR)
{
TRACE("WSAEnumNetworkEvents(...) failure ClientThread\n");
continue;
}
if( ( EventCaused == 3 || EventCaused == 4 )
&& !NetworkEvents.lNetworkEvents )
NetworkEvents.lNetworkEvents = FD_WRITE;
//
// No idea where zero came from...
//
if(!NetworkEvents.lNetworkEvents)
continue;
//
// Process Events
//
if( NetworkEvents.lNetworkEvents & FD_READ
|| m_lenReceive )
{
//
// Do not collect Incomming data, just pass it away to inherited class
//
DWORD NumberOfBytesRecvd;
WSABUF Buffers;
DWORD dwBufferCount = 1;
long maxBuffer = MinLengthMessage — seekCaption;
if( m_lenReceive )
maxBuffer = m_lenReceive;
char szBuffer[ MAX_BUFFER ];
DWORD Flags = 0;
Buffers.buf = szBuffer;
Buffers.len = maxBuffer;
if( Buffers.len > MAX_BUFFER )
Buffers.len = MAX_BUFFER;
result = WSARecv(
s,
&Buffers,
dwBufferCount,
&NumberOfBytesRecvd,
&Flags,
NULL,
NULL);
if(result != SOCKET_ERROR)
{
if( !NumberOfBytesRecvd )
{ // не вычитали ни одного байта
pClientSocketServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId(), pbDataRead );
CoUninitialize( );
return THREADEXIT_SUCCESS;
}
if( !m_lenReceive && seekCaption < MinLengthMessage )
//шапки протокола ещё нет
{
memcpy( szBufferCaption + seekCaption, szBuffer, NumberOfBytesRecvd );
seekCaption += NumberOfBytesRecvd;
}
if( !m_lenReceive )
{
if (seekCaption == MinLengthMessage)
//шапка протокола есть
{
int size;
memcpy( &size, szBufferCaption + 2, 4 );
if( pbDataRead )
delete [] pbDataRead;
m_lenReceive = MinLengthMessage + size;
pbDataRead = new BYTE[ m_lenReceive];
memcpy( pbDataRead, szBufferCaption, MinLengthMessage );
m_seekReceive = MinLengthMessage;
m_lenReceive -= MinLengthMessage;
seekCaption = 0;
if( m_lenReceive )
continue;
}
else
continue;
}
if( !seekCaption && m_lenReceive)
{
memcpy( pbDataRead + m_seekReceive, szBuffer, NumberOfBytesRecvd );
m_seekReceive += NumberOfBytesRecvd;
m_lenReceive -= NumberOfBytesRecvd;
}
if( m_lenReceive > 0 )
continue;
m_lenReceive = 0;
pClientSocketServer->PendingReadArm( pbDataRead, m_seekReceive, pNewConn );
if( !pMsgClient )
continue;
if( pMsgClient->IsNewMsg() )
{
//
// Send Response to client
//
BYTE *pbData = NULL;
long lengthData;
pMsgClient->OutMsg( pbData, lengthData );
if( SOCKET_ERROR == Send( s, pbData, lengthData ) )
{
TRACE("WSASend(...) failure ClientThread, Primary Send\n");
pClientSocketServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId(), pbDataRead );
CoUninitialize( );
return THREADEXIT_SUCCESS;
}
}
if( pMsgClient->IsNewMsgSys() )
{
//
// Send Response to client
//
BYTE *pbData = NULL;
long lengthData;
pMsgClient->OutMsgSys( pbData, lengthData );
if( SOCKET_ERROR == Send( s, pbData, lengthData ) )
{
TRACE("WSASend(...) failure ClientThread, Primary Send\n");
pClientSocketServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId(), pbDataRead );
CoUninitialize( );
return THREADEXIT_SUCCESS;
}
}
}
else
TRACE("WSARecv(...) failure ClientThread\n");
}
if( (NetworkEvents.lNetworkEvents & FD_WRITE)
&& pMsgClient->IsNewMsg() )
{
//
// Send Response to client
//
BYTE *pbData = NULL;
long lengthData;
pMsgClient->OutMsg( pbData, lengthData );
if( SOCKET_ERROR == Send( s, pbData, lengthData ) )
{
TRACE("WSASend(...) failure ClientThread, Primary Send\n");
pClientSocketServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId(), pbDataRead );
CoUninitialize( );
return THREADEXIT_SUCCESS;
}
}
if( (NetworkEvents.lNetworkEvents & FD_WRITE)
&& pMsgClient->IsNewMsgSys() )
{
//
// Send Response to client
//
BYTE *pbData = NULL;
long lengthData;
pMsgClient->OutMsgSys( pbData, lengthData );
if( SOCKET_ERROR == Send( s, pbData, lengthData ) )
{
TRACE("WSASend(...) failure ClientThread, Primary Send\n");
pClientSocketServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId(), pbDataRead );
CoUninitialize( );
return THREADEXIT_SUCCESS;
}
}
if(NetworkEvents.lNetworkEvents & FD_CLOSE)
{
pClientSocketServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId(), pbDataRead );
CoUninitialize( );
return THREADEXIT_SUCCESS;
}
}
CoUninitialize( );
return THREADEXIT_SUCCESS; // We never reach this point
}
void CClientSocketServer::CleanupThread(WSAEVENT Event, SOCKET s, CClientARMConnection* pNewConn, DWORD dwThreadID, BYTE *pbData )
//вызывается при закритии трида клиента
//производит освобождение и закрытие необходимых переменных
{
CleanupThread( Event, s, dwThreadID, pbData );
if( pNewConn )
DeleteMsgClient( pNewConn );
}
void CClientSocketServer::CleanupThread(WSAEVENT Event, SOCKET s, DWORD dwThreadID, BYTE *pbData )
{
if(Event)
WSACloseEvent(Event);
closesocket(s);
if( pbData )
delete pbData;
}
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить