编程语言

img xiangsl

多线程通讯

发表于2004/12/30 15:59:00  1213人阅读

// 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;
}

阅读全文
0 0

相关文章推荐

img
取 消
img