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

📄 genericserver.cpp

📁 一个多线程的http服务器
💻 CPP
📖 第 1 页 / 共 2 页
字号:

		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 + -