Windows下C++实现线程池功能(固定线程数,自动调整未实现)(

http://blog.sina.com.cn/s/blog_6af95663010158j2.html

 

#ifndef PUBLIC_H
#define PUBLIC_H

//测试消息CommandId
const int COMMANDID1_REQ = 0x00000001;
const int COMMANDID1_REP = 0x80000001;

const int COMMANDID2_REQ = 0x00000002;
const int COMMANDID2_REP = 0x80000002;

//消息Body长度
const int MSGBODYLEN = 64;
const int MSGTOTALLEN = 128;

//Message
typedef struct tagCommonHead
{
 u_int uMsgTotalLen;
 u_int uCommandId;
}CommonHead_S;

typedef struct tagMsgStr
{
 CommonHead_S common;
 BYTE cArryMsgBody[MSGBODYLEN];
}MsgStr_S;

#endif


//线程池的基类

#pragma once
#include "stdafx.h"
#include
#include      //支持CCriticalSection
#include    //支持_beginthreadex
#include
#include
using namespace std;

enum Symbol
{
	 CreateThreadSuccess,
	 CreateThreadFailed
};

template    //利用模板实现任务通用
class ThreadPool
{
public:
 	ThreadPool()
 	{
	 	m_CurrentThreadNum = 0;
	  	m_WantedThreadNum = 0;
 	}
	ThreadPool(int nNum)
	{
	  	m_CurrentThreadNum = 0;
	  	m_WantedThreadNum = nNum;
	}

 	virtual ~ThreadPool(){}   //基类的析构函数virtual形式。

	//设置线程数目
	void SetThreadNum(int nNum)
	{
	  	m_WantedThreadNum = nNum;
	}

 	//获取冲突域
 	CCriticalSection& GetCriticalSection()
 	{
  		return m_CriticalSection;
 	}

	//向队列中添加任务
	void AddTask(T* pTask)     //任务类型模板T
	{
	 	GetCriticalSection().Lock();
	 	m_TaskQueue.push(pTask);
	 	m_Event.SetEvent();
	 	GetCriticalSection().Unlock();
	}

 	//创建线程
 	int Run()
 	{
 		m_bTerminateThread = false;
  		HANDLE hHandleThread = NULL;
  		while (m_CurrentThreadNum < m_WantedThreadNum)   //线程池中设定固定个数的线程数
  		{
   			hHandleThread = (HANDLE)_beginthreadex(NULL,
                              0,
                              ThreadPool::LThreadFun,
                              (LPVOID)this,
                              0,
                              &m_ThreadId);        //m_ThreadId为线程ID
   			if (NULL == hHandleThread)
   			{
    			return CreateThreadFailed;
   			}
  			else
   			{
    			m_CurrentThreadNum++;
    			m_vecThreadHandle.push_back(hHandleThread);
   				//AfxMessageBox(_T("Create one thread!"));
   			}
  		}
  		return 0;
 	}

 	//终止线程
 	void TerminateAll()
 	{
  		m_bTerminateThread = true;

  		for (vector::size_type ix=0; ix!=m_vecThreadHandle.size(); ++ix)
  		{
   			HANDLE hHandle = m_vecThreadHandle[ix];
   			if (NULL != hHandle)
   			{
   	 			WaitForSingleObject(hHandle, INFINITE);
    			CloseHandle(hHandle);
    			hHandle = NULL;
    			//AfxMessageBox(_T("close one thread!"));
   			}
  		}
  		m_CurrentThreadNum = 0;
  		m_vecThreadHandle.clear();
 	}

protected:
 	virtual void ProcessFun(T* pTask) = 0;  //纯虚函数,此处真正处理任务

private:
 	static unsigned __stdcall LThreadFun(LPVOID Param)
 	{
 		ThreadPool* pThis = (ThreadPool*)Param;       //派生类对象转为基类
		while (!pThis->m_bTerminateThread)
  		{
   			T* pTask = NULL;
   			pThis->GetCriticalSection().Lock();
   			if (pThis->m_TaskQueue.empty())
   			{
    			pThis->GetCriticalSection().Unlock();
   				if (WAIT_TIMEOUT == WaitForSingleObject((pThis->m_Event).m_hObject, 10))
    			{
     				continue;
    			}
   			}
   		else
   		{
    		pTask = pThis->m_TaskQueue.front();
    		pThis->m_TaskQueue.pop();
    		pThis->GetCriticalSection().Unlock();
    		pThis->ProcessFun(pTask);             //多态调用派生类重写的方法
   		}
  	}
  	return 0;
 }

protected:
 	queue m_TaskQueue;
 	int m_WantedThreadNum;
 	int m_CurrentThreadNum;
 	u_int m_ThreadId;

 	CCriticalSection m_CriticalSection;
 	CEvent m_Event;
 	vector m_vecThreadHandle;   //保存线程HANDLE
 	bool m_bTerminateThread;
};

 

//3. 处理消息的线程池

//1).h文件


#ifndef PROCTHREADPOOL_H
#define PROCTHREADPOOL_H
#include "ThreadPoolBase.h"
#include "Public.h"
#include

class MsgInfo
{
public:
 	SOCKET m_sock;
 	BYTE cArryMsgLen[MSGTOTALLEN];
};

class ProcThreadPool:public ThreadPool
{
public:
 	ProcThreadPool(){}
 	~ProcThreadPool(){}

private:
 	void ProcessFun(MsgInfo* pMsg);
 	u_int GetMsgLen(BYTE cArryMsg[]);
 	u_int GetMsgCommandId(BYTE cArryMsg[]);
 	void DoCommandMsg(u_int uCommand, SOCKET sock);
};
#endif

 

//.cpp文件


#include "stdafx.h"
#include "ProcThreadPool.h"

u_int ProcThreadPool::GetMsgLen(BYTE cArryMsg[])  //封装的获取消息长度的方法
{
 	CommonHead_S* pCommon = (CommonHead_S*)cArryMsg;
 	u_int uMsgLen = ntohl(pCommon->uMsgTotalLen);
 	return uMsgLen;
}

u_int ProcThreadPool::GetMsgCommandId(BYTE cArryMsg[])  //获取CommandId的方法
{
 	CommonHead_S* pCommon = (CommonHead_S*)cArryMsg;
 	u_int uCommandid = ntohl(pCommon->uCommandId);
 	return uCommandid;
}


void ProcThreadPool::DoCommandMsg(u_int uCommand, SOCKET sock)  //根据收到的不同消息,相应处理
{
 	if (COMMANDID1_REQ == uCommand)
 	{
  		MsgStr_S MsgStr;
  		memset(MsgStr.cArryMsgBody, 0, MSGBODYLEN);
  		strcpy((char*)MsgStr.cArryMsgBody, "Command1--Response");
  		MsgStr.common.uCommandId = htonl(COMMANDID1_REP);
  		MsgStr.common.uMsgTotalLen = htonl(sizeof(MsgStr_S));

  		if (SOCKET_ERROR == send(sock, (char*)&MsgStr, sizeof(MsgStr_S), 0))
  		{
   			return;
  		}
 	}
 	else if (COMMANDID2_REQ == uCommand)
 	{
  		MsgStr_S MsgStr;
  		memset(MsgStr.cArryMsgBody, 0, MSGBODYLEN);
  		strcpy((char*)MsgStr.cArryMsgBody, "Command2--Response");
  		MsgStr.common.uCommandId = htonl(COMMANDID2_REP);
  		MsgStr.common.uMsgTotalLen = htonl(sizeof(MsgStr_S));

  		if (SOCKET_ERROR == send(sock, (char*)&MsgStr, sizeof(MsgStr_S), 0))
  		{
   			return;
  		}
 	}
 	else
 	{}

 	return;
}


void ProcThreadPool::ProcessFun(MsgInfo* pMsg)
{
 SOCKET sock = pMsg->m_sock;
 u_int uCommandId = GetMsgCommandId(pMsg->cArryMsgLen);
 u_int uMsgLen = GetMsgLen(pMsg->cArryMsgLen);

 //MsgInfo* pMsgTemp = pMsg;

 switch (uCommandId)
 {
 case COMMANDID1_REQ:
  //处理COMMANDID1消息
  DoCommandMsg(COMMANDID1_REQ, sock);
  break;
 case COMMANDID2_REQ:
  //处理COMMANDID2消息
  DoCommandMsg(COMMANDID2_REQ, sock);
  break;
 default:
  break;
 }

 delete pMsg;
 pMsg = NULL;
 return;
}

 

//4.接收线程池

//1).h文件


#ifndef RECVTHREADPOOL_H
#define RECVTHREADPOOL_H
#include "stdafx.h"
#include "ProcThreadPool.h"

const int RECVTHREADNUM = 5;  //接收线程个数
const int PROCTHREADNUM = 5;  //处理线程个数
const short PORT = 9876;

class RecvThreadPool:public ThreadPool
{
public:
 	RecvThreadPool()
 	{
  		m_bServerRun = false;  //关闭监听线程的标志
 	}

 	~RecvThreadPool(){}

 	int CreateListenThread();   //创建一个监听的线程
 	void StartProcPool(int nNum)     //在接收类中吊起处理线程池
 	{
  		m_ProThreadPool.SetThreadNum(nNum);
  		m_ProThreadPool.Run();
 	}

 	void TerminateProcAll()
 	{
 		m_ProThreadPool.TerminateAll();
 	}

private:
 	void ProcessFun(SOCKET* pSock);
 	u_int GetMsgLen(BYTE cArryMsgLen[]);
 	int RecvTotalMsg();

 	static unsigned __stdcall ListenThread(LPVOID Param);

public:
 	bool m_bServerRun;
private:
 	ProcThreadPool m_ProThreadPool;
};
#endif

 

//2).cpp文件

#include "stdafx.h"
#include "RecvThreadPool.h"

//监听线程
unsigned __stdcall RecvThreadPool::ListenThread(LPVOID Param)
{
 	RecvThreadPool* pThis = (RecvThreadPool*)Param;
 	pThis->StartProcPool(PROCTHREADNUM);  //将处理消息的线程池吊起
 	pThis->SetThreadNum(RECVTHREADNUM);
 	pThis->Run();

 	WSADATA wsaData;
 	int err;
 	err = WSAStartup(MAKEWORD(1, 1), &wsaData);
 	if ( err != 0 )
 	{
 		return 1;
 	}

 	if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
 	{
  		WSACleanup();
  		return 1;
 	}

 	//创建用于监听的套接字
 	SOCKET ListenSock = socket(AF_INET, SOCK_STREAM, 0);

 	SOCKADDR_IN addrSrv;
 	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
 	addrSrv.sin_family = AF_INET;
 	addrSrv.sin_port = htons( PORT );

 	int nOpt=1;
 	setsockopt(ListenSock, SOL_SOCKET, SO_REUSEADDR, (char *) &nOpt, sizeof(int));//重用端口

 	int nRetBind = bind(ListenSock , (SOCKADDR * )&addrSrv, sizeof( SOCKADDR ) );
 	if ( SOCKET_ERROR == nRetBind )
 	{
  		return 1;
 	}

 	int nListenRet = listen( ListenSock, SOMAXCONN);
 	if (SOCKET_ERROR == nListenRet )
 	{
  		return 1;
 	}

 	SOCKADDR_IN addrClient;
 	int len = sizeof( SOCKADDR );

 	fd_set AcceptFdSet;
 	struct timeval tv = {0, 100};

 	while (!pThis->m_bServerRun)
 	{
  		//判断监听SOCKET是否关闭
  		if (INVALID_SOCKET == ListenSock || SOCKET_ERROR == ListenSock)
  		{
   			break;
  		}
  		FD_ZERO(&AcceptFdSet);
  		FD_SET(ListenSock, &AcceptFdSet);
  		int nRetSelect = select(0, &AcceptFdSet, NULL, NULL, &tv);  //Linux下0应该为ListenSock+1

  		if (SOCKET_ERROR == nRetSelect)
  		{
   			break;
  		}
  		if (0 == nRetSelect)//超时
  		{
   			continue;
  		}

  		//等待客户请求到来
  		SOCKET sockConn = accept( ListenSock, ( SOCKADDR * )&addrClient, &len );
  		if (INVALID_SOCKET == sockConn || SOCKET_ERROR == sockConn || NULL == sockConn)
  		{
   			continue;
  		}
  
  		SOCKET* pSock = new SOCKET;
  		*pSock = sockConn;
  		pThis->AddTask(pSock);
 	}

 	AfxMessageBox(_T("Listen thread exit"));
 	WSACleanup();
 	return 0;
}


//创建线程进行监听
int RecvThreadPool::CreateListenThread()
{
 	if (NULL == _beginthreadex(NULL,
        0,
        RecvThreadPool::ListenThread,
        (LPVOID)this,
        0,
        NULL))
 	{
 		return CreateThreadFailed;
 	}

 	return CreateThreadSuccess;
}


//返回消息总长度
u_int RecvThreadPool::GetMsgLen(BYTE cArryMsgLen[])
{
 	CommonHead_S* pCommon = (CommonHead_S*)cArryMsgLen;
 	u_int uMsgLen = ntohl(pCommon->uMsgTotalLen);
 	return uMsgLen;
}


//接收线程池实际处理函数
void RecvThreadPool::ProcessFun(SOCKET* pSock)
{
 	BYTE* pMsgTotal = new BYTE[MSGTOTALLEN];
 	memset(pMsgTotal, 0, MSGTOTALLEN);
 	BYTE* pMsgTotalTemp = pMsgTotal;

 	//先接收消息头
 	int nRecvHeadLen = 0;
 	int nRecvHeadTotalLen = 0;
 	while (1)
 	{
 		nRecvHeadLen = recv(*pSock, (char*)(pMsgTotal + nRecvHeadTotalLen), sizeof(CommonHead_S) -           nRecvHeadTotalLen, 0);
  		if (SOCKET_ERROR == nRecvHeadLen || 0 == nRecvHeadLen)  //0表示对方断开了
  		{
   			return;
  		}
  		nRecvHeadTotalLen += nRecvHeadLen;

  		if (nRecvHeadTotalLen < sizeof(CommonHead_S))
  		{
   			Sleep(200);
   			continue;
  		}
  		if (nRecvHeadTotalLen >= sizeof(CommonHead_S))
  		{
   			break;
  		}
 	}

 	u_int uMsgTotal = GetMsgLen(pMsgTotal);

 	if (uMsgTotal > nRecvHeadTotalLen)  //消息总长度>消息头长度,继续接收消息体
 	{
  		int nRecvBodyLen = 0;
  		int nRecvBodyTotalLen = 0;
  		int nLeftBodyLen = (uMsgTotal - nRecvHeadTotalLen);
  		while (1)
  		{
   			nRecvBodyLen = recv(*pSock, (char*)(pMsgTotal+nRecvHeadTotalLen+nRecvBodyTotalLen),nLeftBodyLen - nRecvBodyTotalLen, 0);
   			if (SOCKET_ERROR == nRecvBodyLen || 0 == nRecvBodyLen)
   			{
    			return;
   			}

   			nRecvBodyTotalLen += nRecvBodyLen;
   			if (nRecvBodyTotalLen < nLeftBodyLen)
   			{
    			continue;
   			}
   			if (nRecvBodyTotalLen >= nLeftBodyLen)
   			{
   				break;
   			}
  		}
 	}

 	MsgInfo* pMsg = new MsgInfo;
 	pMsg->m_sock = *pSock;
 	memset(pMsg->cArryMsgLen, 0, MSGTOTALLEN);
 	memcpy(pMsg->cArryMsgLen, pMsgTotalTemp, MSGTOTALLEN);

 	m_ProThreadPool.AddTask(pMsg);         //处理线程池去处理

 	delete [] pMsgTotalTemp;
 	pMsgTotalTemp = NULL;

 	delete pSock;
 	pSock = NULL;
 	return;
}


转载于:https://www.cnblogs.com/WIT-Evan/p/7291427.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值