📄 genericserver.cpp
字号:
/****************************************************************************************
* ///////////////////////////////////////////////////////////////////////////////////////
* Original Filename: genericserver.cpp
*
* History:
* Created/Modified by Date Main Purpose/Changes
* Souren M. Abeghyan 2001/05/25 Implementation of the CGenericServer class.
*
* Comments:
* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
****************************************************************************************/
#include "stdafx.h"
#include "GenericServer.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGenericServer::CGenericServer()
{
bRun = FALSE;
}
CGenericServer::~CGenericServer()
{
}
void CGenericServer::GetStats(StatisticsTag &st)
{
st.nTotalRecv = Stats.nTotalRecv;
st.nTotalSent = Stats.nTotalSent;
st.nTotalHits = Stats.nTotalHits;
st.nVisitors = Visitors.size();
EnterCriticalSection(&_cs);
st.nClientsConnected = ThreadList.size();
LeaveCriticalSection(&_cs);
}
BOOL CGenericServer::AddClient(SOCKET s, char* ClientAddress, int port)
{
GotConnection(ClientAddress, port);
STRVECT::iterator it;
it = find(Visitors.begin(), Visitors.end(), ClientAddress);
if(it == Visitors.end())
Visitors.push_back(ClientAddress);
InterlockedIncrement(&Stats.nTotalHits);
ThreadTag Thread;
HANDLE hThread;
unsigned int threadID;
EnterCriticalSection(&cs);
NewConnectionTag *NewConn = new NewConnectionTag;
NewConn->pGenericServer = this;
NewConn->s = s;
hThread = (HANDLE)_beginthreadex(NULL, 0, ClientThread, NewConn, 0, &threadID);
if(hThread)
{
Thread.threadID = threadID;
Thread.hThread = hThread;
ThreadList.push_back(Thread);
}
else
LogMessage(LOGFILENAME, "_beginthreadex(...) failure", "AddClient", errno);
LeaveCriticalSection(&cs);
return TRUE;
}
BOOL CGenericServer::Run(int Port, int PersTO)
{
if(bRun)
{
LogMessage(LOGFILENAME, "_beginthreadex(...) failure, for Launch Thread", "Run", errno);
return FALSE;
}
ServerPort = Port;
PersistenceTO = PersTO;
InitializeCriticalSection(&cs);
InitializeCriticalSection(&_cs);
Reset();
ThreadLaunchedEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
// Launch Accept Thread
ResetEvent(ThreadLaunchedEvent);
ThreadA = (HANDLE)_beginthreadex(NULL, 0, AcceptThread, this, 0, &ThreadA_ID);
if(!ThreadA)
{
LogMessage(LOGFILENAME, "_beginthreadex(...) failure, for Launch Thread", "Run", errno);
return FALSE;
}
if(WaitForSingleObject(ThreadLaunchedEvent, THREADWAIT_TO) != WAIT_OBJECT_0)
{
LogMessage(LOGFILENAME, "Unable to get response from Accept Thread withing specified Timeout ->", "Run", THREADWAIT_TO);
CloseHandle(ThreadLaunchedEvent);
return FALSE;
}
// Launch Helper Thread
ResetEvent(ThreadLaunchedEvent);
ThreadC = (HANDLE)_beginthreadex(NULL, 0, HelperThread, this, 0, &ThreadC_ID);
if(!ThreadC)
{
LogMessage(LOGFILENAME, "_beginthreadex(...) failure, for Helper Thread", "Run", errno);
return FALSE;
}
if(WaitForSingleObject(ThreadLaunchedEvent, THREADWAIT_TO) != WAIT_OBJECT_0)
{
LogMessage(LOGFILENAME, "Unable to get response from Helper Thread within specified Timeout ->", "Run", THREADWAIT_TO);
CloseHandle(ThreadLaunchedEvent);
return FALSE;
}
CloseHandle(ThreadLaunchedEvent);
bRun = TRUE;
return TRUE;
}
BOOL CGenericServer::Shutdown()
{
if(!bRun)
return FALSE;
BOOL bResult = TRUE;
HANDLE hArray[2];
hArray[0] = ThreadA;
hArray[1] = ThreadC;
//
// Killing Accept and Helper threads
//
SetEvent(ShutdownEvent);
DWORD n = WaitForMultipleObjects(2, hArray, TRUE, THREADKILL_TO);
if(n == WAIT_TIMEOUT || n == WAIT_FAILED)
{
LogMessage(LOGFILENAME, "WaitForMultipleObjects(...) timed out", "Shutdown");
if(!TerminateThread(ThreadA, THREADEXIT_SUCCESS))
LogMessage(LOGFILENAME, "TerminateThread(.ThreadA.) failure, probably it is already terminated", "Shutdown", GetLastError());
if(!TerminateThread(ThreadC, THREADEXIT_SUCCESS))
LogMessage(LOGFILENAME, "TerminateThread(.ThreadC.) failure, probably it is already terminated", "Shutdown", GetLastError());
bResult = FALSE;
}
CloseHandle(ThreadA);
CloseHandle(ThreadC);
//
// Make sure all client threads are dead
//
THREADLIST::iterator it;
while(ThreadList.size())
{
Sleep(100);
}
DeleteCriticalSection(&cs);
DeleteCriticalSection(&_cs);
bRun = FALSE;
return bResult;
}
void CGenericServer::Reset()
{
//
// Reset statistic values
//
Stats.nClientsConnected = 0;
Stats.nErrosCount = 0;
Stats.nTotalSent = 0;
Stats.nTotalRecv = 0;
Stats.nTotalHits = 0;
Stats.nVisitors = 0;
}
void CGenericServer::CleanupThread(WSAEVENT Event, SOCKET s, NewConnectionTag* pNewConn, DWORD dwThreadID)
{
if(Event)
WSACloseEvent(Event);
closesocket(s);
EnterCriticalSection(&cs);
delete pNewConn;
LeaveCriticalSection(&cs);
THREADLIST::iterator it;
it = find_if(ThreadList.begin(), ThreadList.end(), bind2nd(IDCompare(), dwThreadID));
if(it != ThreadList.end())
{
EnterCriticalSection(&_cs);
HANDLE aaa = (*it).hThread;
HandleList.push_back((*it).hThread);
ThreadList.erase(it);
LeaveCriticalSection(&_cs);
}
else
LogMessage(LOGFILENAME, "Thread not found in the list", "ClientThread");
}
void CGenericServer::CleanupThread(WSAEVENT Event, WSAEVENT ShutdownEvent, SOCKET s)
{
if(Event)
WSACloseEvent(Event);
if(ShutdownEvent)
WSACloseEvent(ShutdownEvent);
if(s)
closesocket(s);
WSACleanup();
}
UINT __stdcall CGenericServer::AcceptThread(LPVOID pParam)
{
CGenericServer *pGenericServer = (CGenericServer*)pParam;
SOCKET s; // Main Listen Socket
WORD wVersionRequested;
WSADATA wsaData;
sockaddr_in saLocal;
WSAEVENT Handles[2];
WSANETWORKEVENTS NetworkEvents;
sockaddr ClientAddr;
INT addrlen = sizeof(ClientAddr);
sockaddr_in sain;
char cAddr[50];
int result;
saLocal.sin_family = AF_INET;
saLocal.sin_port = htons(pGenericServer->ServerPort);
saLocal.sin_addr.s_addr = INADDR_ANY;
wVersionRequested = MAKEWORD(2, 2);
result = WSAStartup(wVersionRequested, &wsaData);
if(result != 0)
{
pGenericServer->LogMessage(LOGFILENAME, "WSAStartup(...) failure", "AcceptThread", result);
return THREADEXIT_SUCCESS;
}
if( LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2)
{
pGenericServer->LogMessage(LOGFILENAME, "Requested Socket version not exist", "AcceptThread");
pGenericServer->CleanupThread(NULL, NULL, NULL);
return THREADEXIT_SUCCESS;
}
s = WSASocket(AF_INET, SOCK_STREAM, 0, (LPWSAPROTOCOL_INFO)NULL, 0, WSA_FLAG_OVERLAPPED);
if(s == INVALID_SOCKET)
{
pGenericServer->LogMessage(LOGFILENAME, "WSASocket(...) failure", "AcceptThread", WSAGetLastError());
pGenericServer->CleanupThread(NULL, NULL, NULL);
return THREADEXIT_SUCCESS;
}
//
// B I N D
//
result = bind(s, (struct sockaddr *)&saLocal, sizeof(saLocal));
if(result == SOCKET_ERROR)
{
pGenericServer->LogMessage(LOGFILENAME, "bind(...) failure", "AcceptThread", WSAGetLastError());
pGenericServer->CleanupThread(NULL, NULL, s);
return THREADEXIT_SUCCESS;
}
//
// L I S T E N
//
result = listen(s, SOMAXCONN);
if(result == SOCKET_ERROR)
{
pGenericServer->LogMessage(LOGFILENAME, "listen(...) failure", "AcceptThread", WSAGetLastError());
pGenericServer->CleanupThread(NULL, NULL, s);
return THREADEXIT_SUCCESS;
}
pGenericServer->ShutdownEvent = WSACreateEvent();
if(pGenericServer->ShutdownEvent == WSA_INVALID_EVENT)
{
pGenericServer->LogMessage(LOGFILENAME, "WSACreateEvent(...) failure for ShutdownEvent", "AcceptThread", WSAGetLastError());
pGenericServer->CleanupThread(NULL, NULL, NULL, s);
return THREADEXIT_SUCCESS;
}
WSAEVENT Event = WSACreateEvent();
if(Event == WSA_INVALID_EVENT)
{
pGenericServer->LogMessage(LOGFILENAME, "WSACreateEvent(...) failure for Event", "AcceptThread", WSAGetLastError());
pGenericServer->CleanupThread(NULL, pGenericServer->ShutdownEvent, s);
return THREADEXIT_SUCCESS;
}
Handles[0] = pGenericServer->ShutdownEvent;
Handles[1] = Event;
result = WSAEventSelect(s, Event, FD_ACCEPT);
if(result == SOCKET_ERROR)
{
pGenericServer->LogMessage(LOGFILENAME, "WSAEventSelect(...) failure", "AcceptThread", WSAGetLastError());
pGenericServer->CleanupThread(Event, pGenericServer->ShutdownEvent, s);
return THREADEXIT_SUCCESS;
}
SetEvent(pGenericServer->ThreadLaunchedEvent);
for(;;)
{
DWORD EventCaused = WSAWaitForMultipleEvents(
2,
Handles,
FALSE,
WSA_INFINITE,
FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -