⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 genericserver.cpp

📁 一个多线程的http服务器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************************
* ///////////////////////////////////////////////////////////////////////////////////////
*	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 + -