// ThreadObj.h: interface for the CThreadObj class.
//
//
#if !defined(THREADOBJ_H)
#define THREADOBJ_H
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "stdtype.h"
#include "lock.h"
#include "sockobj.h"
typedef enum {tpIdle, tpLowest, tpLower, tpNormal,
tpHigher, tpHighest,tpTimeCritical} CThreadPriority;
class CCltThread;
class CSrvThread;
typedef vector< CCltThread* > CCltThreadLst;
typedef vector< CSrvThread* > CSrvThreadLst;
//线程对象基类
class CThreadObj
{
public:
bool m_bFinished;
bool m_bTerminated;//终止线程标志
bool m_bFreeOnTerminate;//在终止线程时是否释放线程
bool m_bSuspended;//悬挂线程
DWORD m_dwReturnValue;//线程返回值
DWORD m_dwThreadID;//线程ID
HANDLE m_hHandle;//线程句柄
CThreadPriority m_Priority;//线程优先级
public:
void Resume();//唤醒线程
void Terminate(){m_bTerminated = true;};//设置终止线程标志
void WaitFor();//等待线程结束
void Create(bool bCreateSuspended=false);//创建线程
static DWORD WINAPI ThreadProc(LPVOID pParam);//线程函数
virtual void Execute() = 0;//线程主函数,线程循环体在此循环
virtual void DoTerminate(){};//终止线程
public:
CThreadObj();
virtual ~CThreadObj();
};
//工作者线程
class CCltThread: public CThreadObj
{
public:
int m_iTimeOut;
bool m_bKeepInCache;//是否保存线程
SOCKET m_ClientSocket;//套接字句柄
HANDLE m_hEvent;//同步事件
CSrvThread* m_pSrvThread;//服务线程指针
public:
virtual bool DoRead();
virtual void Execute();//线程主函数,线程循环体在此循环
virtual void ClientExecute();//客户端线程处理函数
void Disconnect();
void DoTerminate();//结束线程
void ReActivate(SOCKET socket);//重新启用线程
bool StartConnect();//开始连接
bool EndConnect();//终止连接
bool Connected();
public:
CCltThread(SOCKET sock, CSrvThread* pSrvThread, bool bCreateSuspended=false);
CCltThread(){};
virtual ~CCltThread();
};
class CSrvThread: public CThreadObj
{
protected:
UINT m_iThreadCacheSize;
bool m_bActive;
SOCKET m_SrvSock;
CSockLst m_Connections;
CLockObjCS m_LockObjCS;
CCltThreadLst m_ActiveThreads;
public:
int m_iPort;
bool Connected();
void AddClient(SOCKET CltSock);
void RemoveClient(SOCKET CltSock);
void AddThread(CCltThread* pThread);
void RemoveThread(CCltThread* pThread);
void GetSrvCltThread(SOCKET CltSock);
void SetPort(int port){m_iPort = port;};
void SetActive(bool bActive);
void Disconnect();
void Listen();
SOCKET Accept();
public:
int GetActiveConnections();
int GetActiveThreads();
int GetIdleThreads();
virtual void Init();
public:
CSrvThread();
virtual void Execute();
virtual void DoCreateThread(SOCKET CltSock);
};
#endif
// ThreadObj.cpp: implementation of the CThreadObj class.
//
//
#include "ThreadObj.h"
//
// Construction/Destruction
//
CThreadObj::CThreadObj()
{
m_hHandle = (HANDLE)-1;
m_dwReturnValue = 0;
m_dwThreadID = 0;
m_bTerminated = false;
m_bFreeOnTerminate = false;
m_bSuspended = false;
m_bFinished = false;
}
CThreadObj::~CThreadObj()
{
CloseHandle(m_hHandle);
}
void CThreadObj::Resume()
{
if (ResumeThread(m_hHandle) == 1)
m_bSuspended = false;
}
//创建线程
void CThreadObj::Create(bool bCreateSuspended)
{
m_bSuspended = bCreateSuspended;
DWORD dwFlags = 0;
if (bCreateSuspended)
dwFlags = CREATE_SUSPENDED;
m_hHandle = BeginThreadex(0, 0, &ThreadProc, this, dwFlags, &m_dwThreadID);
}
//线程函数
DWORD CThreadObj::ThreadProc(LPVOID pParam)
{
CThreadObj* pBaseThread = (CThreadObj*)pParam;
try{
pBaseThread->Execute();
}catch(...){}
//结束时是否释放线程对象
bool bFreeThread = pBaseThread->m_bFreeOnTerminate;
//设置线程返回值
DWORD Result = pBaseThread->m_dwReturnValue;
//设置线程完成标志
pBaseThread->m_bFinished = true;
//调用线程终止函数
pBaseThread->DoTerminate();
if (bFreeThread)
delete pBaseThread;
ExitThread(Result);
return Result;
}
void CThreadObj::WaitFor()
{
WaitForSingleObject(m_hHandle, INFINITE);
}
//创建客户端线程,同时设置该线程的连接句柄和服务线程的句柄
CCltThread::CCltThread(SOCKET sock, CSrvThread* pSrvThread, bool bCreateSuspended)
{
m_hEvent = CreateEvent(NULL, false, true, NULL);
m_ClientSocket = sock;
m_pSrvThread = pSrvThread;
m_bKeepInCache = false;
m_bFreeOnTerminate = true;
//Priority := tpHigher;
ReActivate(sock);
//if (!bCreateSuspended)
//Resume;
}
CCltThread::~CCltThread()
{
CloseHandle(m_hEvent);
}
//终止线程,将线程对象自身从服务线程的列表中删除,由基类线程函数调用
void CCltThread::DoTerminate()
{
if (NULL != m_pSrvThread)
m_pSrvThread->RemoveThread(this);
}
//线程主函数,线程循环体在此循环
void CCltThread::Execute()
{
try{//线程处理循环体
while (true){
if (StartConnect())//阻塞直到连接事件到来
ClientExecute();//对新连接进行处理
if (EndConnect())//终止当前连接,返回线程结束条件
break;
}
}catch(...){
m_bKeepInCache = false;
}
}
//客户端处理函数,由其子类重载
void CCltThread::ClientExecute()
{
//当前连接处理循环体
while (!m_bTerminated && Connected()) {
FD_SET fd = {1, m_ClientSocket};
TIMEVAL tv = {m_iTimeOut, 0};
unsigned long flag = 1;
int nBytesRecv=0;
if (select(0, &fd, NULL, NULL, &tv) > 0 && !m_bTerminated) {
ioctlsocket(m_ClientSocket, FIONREAD, (u_long*)&nBytesRecv);
if (0 == nBytesRecv) {
this->Disconnect();
break;
}
}else {
this->Disconnect();
break;
}
}
}
//接受数据
bool CCltThread::DoRead()
{
return true;
}
//解除连接
void CCltThread::Disconnect()
{
//假如没有连接,则不作处理
if (!Connected())
return;
//从服务线程的列表中删除当前连接
m_pSrvThread->RemoveClient(m_ClientSocket);
CSockObj Clt;
//关闭套接字
Clt.CloseSocket(m_ClientSocket);
//重置套接字句柄
m_ClientSocket = INVALID_SOCKET;
}
//返回是否建立了连接,连接建立返回TRUE,否则返回FALSE
bool CCltThread::Connected()
{
return !(m_ClientSocket == INVALID_SOCKET);
}
//有新的连接到来后,重新激活线程
void CCltThread::ReActivate(SOCKET socket)
{
m_ClientSocket = socket;
//将当前客户线程添加到服务线程的列表中
m_pSrvThread->AddThread(this);
//终止线程的等待,重新启动线程处理函数
SetEvent(m_hEvent);
}
//等待连接事件,重新启动线程处理函数
bool CCltThread::StartConnect()
{
WaitForSingleObject(m_hEvent, INFINITE);
return !m_bTerminated;
}
//线程处理函数完毕,结束连接
bool CCltThread::EndConnect()
{
//用户终止,或者连接处理完毕,又不需要保存当前线程返回TRUE
return m_bTerminated || !m_bKeepInCache;
}
//将当前连接添加到列表中
void CSrvThread::AddClient(SOCKET CltSock)
{
CLock lock(&m_LockObjCS);
if ( find(m_Connections.begin(), m_Connections.end(), CltSock)
== m_Connections.end() ){
m_Connections.push_back(CltSock);
string szLog = "++连接:" + FmtInt(CltSock, 5, '0') + "建立连接时间为:" +
GetSysStrTime() + ",当前连接数为:" +
FmtInt(m_Connections.size(), 4, '0') + "/r/n";
printf(szLog.c_str());
}
}
void CSrvThread::RemoveClient(SOCKET CltSock)
{
CLock lock(&m_LockObjCS);
CSockLst::iterator pos;
pos = find(m_Connections.begin(), m_Connections.end(), CltSock);
if (pos != m_Connections.end()) {
m_Connections.erase(pos);
string szLog = "--连接:" + FmtInt(CltSock, 5, '0') + "解除连接时间为:" +
GetSysStrTime() + ",当前连接数为:" +
FmtInt(m_Connections.size(), 4, '0') + "/r/n";
printf(szLog.c_str());
}
}
void CSrvThread::AddThread(CCltThread* pThread)
{
CLock lock(&m_LockObjCS);
if (m_ActiveThreads.end() == find(m_ActiveThreads.begin(),
m_ActiveThreads.end(), pThread))
{
m_ActiveThreads.push_back(pThread);
if (m_ActiveThreads.size() <= m_iThreadCacheSize)
pThread->m_bKeepInCache = true;
else
pThread->m_bKeepInCache = false;
}
}
void CSrvThread::RemoveThread(CCltThread* pThread)
{
CLock lock(&m_LockObjCS);
CCltThreadLst::iterator pos;
pos = find(m_ActiveThreads.begin(), m_ActiveThreads.end(), pThread);
if (pos != m_ActiveThreads.end())
m_ActiveThreads.erase(pos);
}
int CSrvThread::GetActiveConnections()
{
//CLock lock(&m_CSLockObj);
return m_Connections.size();
}
int CSrvThread::GetActiveThreads()
{
CLock lock(&m_LockObjCS);
int iActiveCount = 0;
for (size_t i=0; i<m_ActiveThreads.size(); ++i)
if (m_ActiveThreads[i]->Connected())
++iActiveCount;
return iActiveCount;
}
int CSrvThread::GetIdleThreads()
{
CLock lock(&m_LockObjCS);
int iIdleCount = 0;
for (size_t i=0; i<m_ActiveThreads.size(); ++i)
if (!m_ActiveThreads[i]->Connected())
++iIdleCount;
return iIdleCount;
}
void CSrvThread::Init()
{
}
//线程执行主体,假如没有人为终止线程,则循环接收连接
void CSrvThread::Execute()
{
string szLog = GetSysStrTime() + " 服务[" + FmtInt(m_iPort, 5, '0') + "]启动成功/r/n";
printf(szLog.c_str());
while (!m_bTerminated)
Accept();
}
//设置服务线程的活动状态
void CSrvThread::SetActive(bool bActive)
{
if (bActive != m_bActive) {
m_bActive = bActive;
if (Connected())//假如已连接,解除连接
Disconnect();
else//未连接则启动
Listen();
}
}
//服务线程终止连接,与所有客户端断开连接
void CSrvThread::Disconnect()
{
int iSaveCacheSize = m_iThreadCacheSize;
Terminate();//调用终止线程处理函数,该函数会将线程标志设置为false
m_iThreadCacheSize = 0;
CCltThread* pCltThread;
while (0 != m_ActiveThreads.size()) {
pCltThread = m_ActiveThreads[0];
pCltThread->m_bFreeOnTerminate = false;
pCltThread->Terminate();
//如果客户端线程处于阻塞,则重新激活
SetEvent(pCltThread->m_hEvent);
pCltThread->WaitFor();
pCltThread->Disconnect();
delete pCltThread;
/*
//如果线程仍处于活动连接中,则通过关闭套接字来结束连接状态
if (m_ActiveThreads[i]->m_ClientSocket != INVALID_SOCKET){
CSockObj Clt;
//关闭套接字
Clt.CloseSocket(m_ActiveThreads[i]->m_ClientSocket);
}
*/
}
m_iThreadCacheSize = iSaveCacheSize;
if ( Connected() ){//如果连接服务任然是活动的,则关闭连接
CSockObj Srv;
Srv.CloseSocket(m_SrvSock);
m_SrvSock = INVALID_SOCKET;
}
}
//启动服务线程
void CSrvThread::Listen()
{
Init();
CSockObj Srv;
m_SrvSock = Srv.CreateSocket();
if (m_SrvSock == INVALID_SOCKET)
return ;
if (0 == m_iPort)
m_iPort = 75333;
Srv.BindSocketEx(m_SrvSock, m_iPort);
Srv.ListenSocket(m_SrvSock, 100);
Create();
}
//接受客户端连接
SOCKET CSrvThread::Accept()
{
CSockObj Srv;
SOCKET CltSock = Srv.Accept_Block(m_SrvSock);//接受客户端连接
if (CltSock != INVALID_SOCKET) {
AddClient(CltSock);//将当前客户端连接添加到列表中
GetSrvCltThread(CltSock);//得到用于服务的客户端线程
};
return CltSock;
}
//取得用于服务的客户端线程
void CSrvThread::GetSrvCltThread(SOCKET CltSock)
{
CLock lock(&m_LockObjCS);
size_t i;
//寻找空闲的客户端线程
for (i=0; i<m_ActiveThreads.size(); ++i)
if ( m_ActiveThreads[i]->m_ClientSocket == INVALID_SOCKET ){
m_ActiveThreads[i]->ReActivate(CltSock);//如果找到,则激活
break;
}
//如果没有找到则创建新线程
if (m_ActiveThreads.size() == i)
DoCreateThread(CltSock);
}
void CSrvThread::DoCreateThread(SOCKET CltSock)
{
(new CCltThread(CltSock, this, false))->Create();
}
//返回服务线程的连接状态
bool CSrvThread::Connected()
{
return !(m_SrvSock == INVALID_SOCKET);
}
CSrvThread::CSrvThread()
{
m_iThreadCacheSize = 100;
m_bActive = false;
m_SrvSock = INVALID_SOCKET;
m_iPort = 0;
}