📄 genericserver.cpp
字号:
if(EventCaused == WAIT_FAILED || EventCaused == WAIT_OBJECT_0)
{
if(EventCaused == WAIT_FAILED)
pGenericServer->LogMessage(LOGFILENAME, "WaitForMultipleObjects(...) failure", "AcceptThread", GetLastError());
pGenericServer->CleanupThread(Event, pGenericServer->ShutdownEvent, s);
return THREADEXIT_SUCCESS;
}
result = WSAEnumNetworkEvents(
s,
Event,
&NetworkEvents);
if(result == SOCKET_ERROR)
{
pGenericServer->LogMessage(LOGFILENAME, "WSAEnumNetworkEvents(...) failure", "AcceptThread", WSAGetLastError());
pGenericServer->CleanupThread(Event, pGenericServer->ShutdownEvent, s);
return THREADEXIT_SUCCESS;
}
if(NetworkEvents.lNetworkEvents == FD_ACCEPT)
{
SOCKET ClientSocket = WSAAccept(s, &ClientAddr, &addrlen, NULL, NULL);
memcpy(&sain, &ClientAddr, addrlen);
sprintf(cAddr, "%d.%d.%d.%d",
sain.sin_addr.S_un.S_un_b.s_b1,
sain.sin_addr.S_un.S_un_b.s_b2,
sain.sin_addr.S_un.S_un_b.s_b3,
sain.sin_addr.S_un.S_un_b.s_b4);
if(INVALID_SOCKET == ClientSocket)
{
pGenericServer->LogMessage(LOGFILENAME, "WSAAccept(...) failure", "AcceptThread", WSAGetLastError());
// I think there is no reason to shutdown whole server if just one connection failed
continue;
}
else
{
if(!pGenericServer->AddClient(ClientSocket, cAddr, sain.sin_port))
{
pGenericServer->LogMessage(LOGFILENAME, "AddClient(...) failure", "AcceptThread");
continue; // I think there is no reason to shutdown whole server if just one connection failed
}
}
}
}
pGenericServer->CleanupThread(Event, pGenericServer->ShutdownEvent, s);
return THREADEXIT_SUCCESS;
}
unsigned __stdcall CGenericServer::ClientThread(LPVOID pParam)
{
NewConnectionTag *pNewConn = (NewConnectionTag*)pParam;
CGenericServer *pGenericServer = pNewConn->pGenericServer;
SOCKET s = pNewConn->s;
int result;
WSAEVENT EventArray[2];
WSANETWORKEVENTS NetworkEvents;
BOOL bResend = FALSE;
WSABUF Buffer;
DWORD NumberOfBytesSent;
DWORD dwBytesSent;
BOOL bKeepAlive = FALSE;
string szRequest;
string szResponse;
WSAEVENT Event = WSACreateEvent();
if(Event == WSA_INVALID_EVENT)
{
pGenericServer->LogMessage(LOGFILENAME, "WSACreateEvent(...) failure", "ClientThread", WSAGetLastError());
pGenericServer->CleanupThread(NULL, s, pNewConn, GetCurrentThreadId());
return THREADEXIT_SUCCESS;
}
result = WSAEventSelect(s, Event, FD_READ | FD_WRITE | FD_CLOSE);
if(result == SOCKET_ERROR)
{
pGenericServer->LogMessage(LOGFILENAME, "WSAEventSelect(...) failure", "ClientThread", WSAGetLastError());
pGenericServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId());
return THREADEXIT_SUCCESS;
}
EventArray[0] = Event;
EventArray[1] = pGenericServer->ShutdownEvent;
for(;;)
{
DWORD EventCaused = WSAWaitForMultipleEvents(
2,
EventArray,
FALSE,
pGenericServer->PersistenceTO ? pGenericServer->PersistenceTO : WSA_INFINITE,
FALSE);
if(WSA_WAIT_FAILED == EventCaused)
{
pGenericServer->LogMessage(LOGFILENAME, "WSAWaitForMultipleEvents(...) failure", "ClientThread", WSAGetLastError());
pGenericServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId());
return THREADEXIT_SUCCESS;
}
//
// Check if our Server mission is over or Client established connection, but no request so far
//
if(EventCaused == 1 || EventCaused == WSA_WAIT_TIMEOUT)
{
pGenericServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId());
return THREADEXIT_SUCCESS;
}
//
// Determine which network event occured
//
result = WSAEnumNetworkEvents(
s,
Event,
&NetworkEvents);
if(result == SOCKET_ERROR)
{
pGenericServer->LogMessage(LOGFILENAME, "WSAEnumNetworkEvents(...) failure", "ClientThread", WSAGetLastError());
continue;
}
//
// No idea where zero came from...
//
if(!NetworkEvents.lNetworkEvents)
continue;
//
// Process Events
//
if(NetworkEvents.lNetworkEvents & FD_READ)
{
//
// Do not collect Incomming data, just pass it away to inherited class
//
DWORD NumberOfBytesRecvd;
WSABUF Buffers;
DWORD dwBufferCount = 1;
char szBuffer[MAX_BUFFER];
DWORD Flags = 0;
Buffers.buf = szBuffer;
Buffers.len = MAX_BUFFER;
result = WSARecv(
s,
&Buffers,
dwBufferCount,
&NumberOfBytesRecvd,
&Flags,
NULL,
NULL);
if(result != SOCKET_ERROR)
{
pGenericServer->Stats.nTotalRecv += (double)NumberOfBytesRecvd / 1024;
//
// Chech if we got complete request
//
szRequest += string(szBuffer, NumberOfBytesRecvd);
if(!pGenericServer->IsComplete(szRequest))
continue;
if(!pGenericServer->ParseRequest(szRequest, szResponse, bKeepAlive))
{
pGenericServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId());
return THREADEXIT_SUCCESS;
}
//
// Send Response to client
//
NumberOfBytesSent = 0;
dwBytesSent = 0;
do
{
Buffer.len = (szResponse.size() - dwBytesSent) >= SENDBLOCK ? SENDBLOCK : szResponse.size() - dwBytesSent;
Buffer.buf = (char*)((DWORD)szResponse.c_str() + dwBytesSent);
result = WSASend(
s,
&Buffer,
1,
&NumberOfBytesSent,
0,
0,
NULL);
if(SOCKET_ERROR != result)
dwBytesSent += NumberOfBytesSent;
}
while((dwBytesSent < szResponse.size()) && SOCKET_ERROR != result);
if(WSAGetLastError() == WSAEWOULDBLOCK)
{
bResend = TRUE;
continue;
}
if(SOCKET_ERROR != result)
{
pGenericServer->Stats.nTotalSent += (double)dwBytesSent / 1024;
pGenericServer->DataSent(dwBytesSent);
}
else
{
pGenericServer->LogMessage(LOGFILENAME, "WSASend(...) failure", "ClientThread, Primary Send", WSAGetLastError());
bKeepAlive = FALSE;
}
if(!bKeepAlive)
{
pGenericServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId());
return THREADEXIT_SUCCESS;
}
//
// We are finished with this request, clear buffer for next one
//
szRequest.erase(0, string::npos);
}
else
pGenericServer->LogMessage(LOGFILENAME, "WSARecv(...) failure", "ClientThread", WSAGetLastError());
}
if((NetworkEvents.lNetworkEvents & FD_WRITE) && bResend)
{
//
// Send Response to client
//
do
{
Buffer.len = (szResponse.size() - dwBytesSent) >= SENDBLOCK ? SENDBLOCK : szResponse.size() - dwBytesSent;
Buffer.buf = (char*)((DWORD)szResponse.c_str() + dwBytesSent);
result = WSASend(
s,
&Buffer,
1,
&NumberOfBytesSent,
0,
0,
NULL);
if(SOCKET_ERROR != result)
dwBytesSent += NumberOfBytesSent;
}
while((dwBytesSent < szResponse.size()) && SOCKET_ERROR != result);
if(WSAGetLastError() == WSAEWOULDBLOCK)
{
bResend = TRUE;
continue;
}
if(SOCKET_ERROR != result)
{
pGenericServer->Stats.nTotalSent += (double)dwBytesSent / 1024;
pGenericServer->DataSent(dwBytesSent);
}
else
{
pGenericServer->LogMessage(LOGFILENAME, "WSASend(...) failure", "ClientThread, Primary Send", WSAGetLastError());
bKeepAlive = FALSE;
}
if(!bKeepAlive)
{
pGenericServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId());
return THREADEXIT_SUCCESS;
}
bResend = FALSE;
//
// We are finished with this request, clear the buffer for next one
//
szRequest.erase(0, string::npos);
}
if(NetworkEvents.lNetworkEvents & FD_CLOSE)
{
pGenericServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId());
return THREADEXIT_SUCCESS;
}
}
return THREADEXIT_SUCCESS; // We never reach this point
}
UINT __stdcall CGenericServer::HelperThread(LPVOID pParam)
{
CGenericServer *pGenericServer = (CGenericServer*)pParam;
HANDLELIST::iterator it;
SetEvent(pGenericServer->ThreadLaunchedEvent);
for(;;)
{
if(WaitForSingleObject(pGenericServer->ShutdownEvent, TICK) == WAIT_TIMEOUT)
{
EnterCriticalSection(&pGenericServer->_cs);
while(pGenericServer->HandleList.size())
{
HANDLE h = pGenericServer->HandleList.front();
DWORD n = WaitForSingleObject(h, THREADKILL_TO);
if(n == WAIT_TIMEOUT)
{
pGenericServer->LogMessage(LOGFILENAME, "WaitForSingleObject(...) timed out", "HelperThread");
if(!TerminateThread(h, THREADEXIT_SUCCESS))
pGenericServer->LogMessage(LOGFILENAME, "TerminateThread(.h.) failure, probably it is already terminated", "HelperThread", GetLastError());
}
CloseHandle(h);
pGenericServer->HandleList.pop_front();
}
LeaveCriticalSection(&pGenericServer->_cs);
}
else
return THREADEXIT_SUCCESS;
}
return THREADEXIT_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -