www.gusucode.com > VC++写的小型HTTP服务器源程序-源码程序 > VC++写的小型HTTP服务器源程序-源码程序\code\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 // Download by http://www.NewXing.com ////////////////////////////////////////////////////////////////////// // 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); // 启动接收线程 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; } // 启动帮助线程 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; // // 关闭接收和helper线程 // 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); // // 所有的客户线程都结束 // 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; // 主线程 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; } // // 绑定 // 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; } // // 侦听 // 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); 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()); // 有一个文件错误 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; } // // 检查是否服务器任务已经完成 // if(EventCaused == 1 || EventCaused == WSA_WAIT_TIMEOUT) { pGenericServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId()); return THREADEXIT_SUCCESS; } // // 分析什么网络事件产生 // result = WSAEnumNetworkEvents( s, Event, &NetworkEvents); if(result == SOCKET_ERROR) { pGenericServer->LogMessage(LOGFILENAME, "WSAEnumNetworkEvents(...) failure", "ClientThread", WSAGetLastError()); continue; } // // 其他情况 // if(!NetworkEvents.lNetworkEvents) continue; // // 处理事件 // if(NetworkEvents.lNetworkEvents & FD_READ) { // // 不需要接收接传入的数据,只需要传给继承类 // 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; // // 检测是否获得完整的请求 // szRequest += string(szBuffer, NumberOfBytesRecvd); if(!pGenericServer->IsComplete(szRequest)) continue; if(!pGenericServer->ParseRequest(szRequest, szResponse, bKeepAlive)) { pGenericServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId()); return THREADEXIT_SUCCESS; } // // 发送响应倒客户端 // 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; } // // 完成请求,清除缓冲区 // szRequest.erase(0, string::npos); } else pGenericServer->LogMessage(LOGFILENAME, "WSARecv(...) failure", "ClientThread", WSAGetLastError()); } if((NetworkEvents.lNetworkEvents & FD_WRITE) && bResend) { // // 发送响应倒客户端 // 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; // // 清除缓冲区 // szRequest.erase(0, string::npos); } if(NetworkEvents.lNetworkEvents & FD_CLOSE) { pGenericServer->CleanupThread(Event, s, pNewConn, GetCurrentThreadId()); return THREADEXIT_SUCCESS; } } return THREADEXIT_SUCCESS; // } 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; }