1、zzcServer类,用于完成对客户端连接的监听操作:
.h文件:
#pragma once
#include "event2/event.h"
#include "event2/listener.h"
#include "event2/thread.h"
class zzcServer
{
public:
zzcServer(void);
~zzcServer(void);
//开启服务
bool RunServ();
private:
//初始化socket网络库
void InitSocket();
//开启主线程事件循环
static unsigned __stdcall MainThreadEventDispatch(void* param);
//监听回调函数
static void listen_cb(struct evconnlistener * e, evutil_socket_t s, struct sockaddr *a, int socklen, void *arg);
private:
//监听端口号
short m_sPort;
//主循环线程句柄
HANDLE m_hThread;
//环境上下文
event_base *m_pBase;
//监听器
evconnlistener *m_pEv;
};
.cpp文件:
#include "StdAfx.h"
#include "zzcServer.h"
#include "MyTask.h"
#include "zzcThreadPoor.h"
using namespace std;
zzcServer::zzcServer(void)
{
m_sPort = 6000;
m_pBase = NULL;
m_pEv = NULL;
m_hThread = INVALID_HANDLE_VALUE;
InitSocket();
}
zzcServer::~zzcServer(void)
{
#ifdef _WIN32
WSACleanup();
#endif
if (m_hThread)
{
CloseHandle(m_hThread);
m_hThread = INVALID_HANDLE_VALUE;
}
}
void zzcServer::InitSocket()
{
#ifdef _WIN32
WSADATA wsa;
WSAStartup(MAKEWORD(2,2), &wsa);
#else
if(signal(SIGPIPE, SIG_IGN) == SIG_ERR)
return false;
#endif
}
void zzcServer::listen_cb(struct evconnlistener * e, evutil_socket_t s, struct sockaddr *a, int socklen, void *arg)
{
zzcTask *task = new MyTask();
task->m_sock = s;
zzcThreadPoor::GetInstance()->Dispatch(task);
}
bool zzcServer::RunServ()
{
int nRet = -1;
bool bRet = false;
event_config *pcfg = NULL;
do
{
//初始化线程池
zzcThreadPoor::GetInstance()->Init(10);
if ((pcfg = event_config_new()) == NULL)
{
break;
}
if (-1 == (nRet = event_config_set_flag(pcfg, EVENT_BASE_FLAG_STARTUP_IOCP)))
{
break;
}
SYSTEM_INFO si;
memset(&si, 0, sizeof(si));
GetSystemInfo(&si);
if ((nRet = event_config_set_num_cpus_hint(pcfg, si.dwNumberOfProcessors)) == -1)
{
break;
}
if ((nRet = evthread_use_windows_threads()) == -1)
{
break;
}
if ((m_pBase = event_base_new_with_config(pcfg)) == NULL)
{
if((m_pBase = event_base_new()) == NULL)
{
break;
}
}
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(m_sPort);
if ((m_pEv = evconnlistener_new_bind(m_pBase, // libevent的上下文
listen_cb, //接收到连接的回调函数
m_pBase, //回调函数获取的参数 arg
LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,//地址重用,evconnlistener关闭同时关闭socket
10, //连接队列大小,对应listen函数
(sockaddr*)&sin, //绑定的地址和端口
sizeof(sin)
)) == NULL)
{
break;
}
if (INVALID_HANDLE_VALUE == (m_hThread = (HANDLE)_beginthreadex( NULL, 0, &MainThreadEventDispatch, (void*)this, 0, NULL)))
{
break;
}
bRet = true;
} while (false);
if (false == bRet)
{
if (pcfg)
event_config_free(pcfg);
if (m_pEv)
evconnlistener_free(m_pEv);
if(m_pBase)
event_base_free(m_pBase);
return false;
}
return true;
}
unsigned __stdcall zzcServer::MainThreadEventDispatch(void* param)
{
zzcServer* pThis = (zzcServer*)param;
if (pThis->m_pBase)
event_base_dispatch(pThis->m_pBase);
if (pThis->m_pEv)
evconnlistener_free(pThis->m_pEv);
if(pThis->m_pBase)
event_base_free(pThis->m_pBase);
_endthreadex(0);
return 0;
}
2.zzcThreadPoor类,主要是启动管道通信初始化,从而进行任务的分发:
.h文件:
#pragma once
#include <vector>
class zzcThread;
class zzcTask;
class zzcThreadPoor
{
public:
~zzcThreadPoor(void);
static zzcThreadPoor* GetInstance()
{
static zzcThreadPoor tp;
return &tp;
}
//初始化线程池中的线程并启动
void Init(int threadCount);
//负载均衡法分发线程
void Dispatch(zzcTask *task);
private:
zzcThreadPoor(void);
void Release();
private:
//池中线程总数量
int m_nThreadCount;
//当前分配线程索引
int m_nThreadIndex;
//存放线程池中的线程
std::vector<zzcThread*> m_vThreads;
};
.cpp文件:
#include "StdAfx.h"
#include "zzcThreadPoor.h"
#include "zzcThread.h"
#include "zzcTask.h"
using namespace std;
zzcThreadPoor::zzcThreadPoor(void)
{
m_nThreadCount = 0;
m_nThreadIndex = -1;
}
zzcThreadPoor::~zzcThreadPoor(void)
{
Release();
}
void zzcThreadPoor::Release()
{
vector<zzcThread*>::iterator it;
for (it = m_vThreads.begin();it != m_vThreads.end();++it)
{
if (*it)
{
delete *it,*it = NULL;
}
}
m_vThreads.clear();
}
void zzcThreadPoor::Init(int threadCount)
{
this->m_nThreadCount = threadCount;
this->m_nThreadIndex = -1;
for (int i = 0;i < threadCount;++i)
{
zzcThread *t = new zzcThread();
t->m_nThreadID = i + 1;
//启动线程
t->Start();
m_vThreads.push_back(t);
Sleep(10);
}
}
void zzcThreadPoor::Dispatch(zzcTask *task)
{
if(!task || m_vThreads.size() == 0 || m_nThreadCount == 0)
return;
int nCurID = (m_nThreadIndex + 1) % m_nThreadCount;
m_nThreadIndex = nCurID;
zzcThread *t = m_vThreads[nCurID];
t->AddTask(task);
//激活线程
t->Activate();
}
3、zzcThread类,接收主线程的管道消息,从而对接相应的客户端:
.h文件:
#pragma once
#include "event2/event.h"
#include <list>
class zzcTask;
class zzcThread
{
public:
zzcThread(void);
~zzcThread(void);
//开启线程
bool Start();
//激活子线程
bool Activate();
//初始化管道,用于主线程和子线程之间的通信,主线程通知相应的子线程客户端连接进来了
bool InitPipe();
//管道回调函数,水平触发
static void pipe_process(evutil_socket_t fd, short which, void *arg);
//开启子线程事件循环
static unsigned __stdcall SubThreadEventDispatch(void* param);
//向线程添加任务
void AddTask(zzcTask *t);
private:
//子线程环境上下文
struct event_base *m_pBase;
//写管道描述符
evutil_socket_t m_nWritePipe;
//子循环线程句柄
HANDLE m_hThread;
//任务列表
std::list<zzcTask*> m_lTask;
//任务队列锁
CMutex m_mutex;
public:
//线程编号
int m_nThreadID;
};
.cpp文件:
#include "StdAfx.h"
#include "zzcThread.h"
#include "zzcTask.h"
zzcThread::zzcThread(void)
{
m_pBase = NULL;
m_nWritePipe = 0;
m_nThreadID = 0;
m_hThread = INVALID_HANDLE_VALUE;
}
zzcThread::~zzcThread(void)
{
if (m_hThread)
{
CloseHandle(m_hThread);
m_hThread = INVALID_HANDLE_VALUE;
}
}
void zzcThread::AddTask(zzcTask *t)
{
if(!t)
return;
if(NULL != this->m_pBase)
t->m_pBase = this->m_pBase;
CSingleLock lock(&m_mutex);
lock.Lock();
m_lTask.push_back(t);
lock.Unlock();
}
bool zzcThread::Activate()
{
#ifdef _WIN32
int bRet = send(this->m_nWritePipe, "c", 1, 0);
#else
int bRet = write(this->m_nWritePipe, "c", 1);
#endif
if (bRet <= 0)
{
return false;
}
return true;
}
void zzcThread::pipe_process(evutil_socket_t fd, short which, void *arg)
{
zzcThread* pThis = (zzcThread*)arg;
int nRet = 0;
char szbuf[2] = {0};
#ifdef _WIN32
nRet = recv(fd, szbuf, 1, 0);
#else
nRet = read(fd, szbuf, 1);
#endif
if (nRet <= 0)
return;
zzcTask *task = NULL;
CSingleLock lock(&pThis->m_mutex);
lock.Lock();
if (pThis->m_lTask.empty())
{
lock.Unlock();
return;
}
task = pThis->m_lTask.front();
pThis->m_lTask.pop_front();
lock.Unlock();
if(task)
task->Init();
}
unsigned __stdcall zzcThread::SubThreadEventDispatch(void* param)
{
zzcThread* pThis = (zzcThread*)param;
if (pThis->m_pBase)
event_base_dispatch(pThis->m_pBase);
if (pThis->m_pBase)
event_base_free(pThis->m_pBase);
_endthreadex(0);
return 0;
}
bool zzcThread::Start()
{
return InitPipe();
}
bool zzcThread::InitPipe()
{
bool bRet = false;
event *ev = NULL;
event_config *ev_conf = NULL;
#ifdef _WIN32
evutil_socket_t fds[2];
if (evutil_socketpair(AF_INET, SOCK_STREAM, 0, fds) < 0)
{
return bRet;
}
//fds[0]读;fds[1]写
if ((-1 == evutil_make_socket_nonblocking(fds[0])) || (-1 == evutil_make_socket_nonblocking(fds[1])))
{
return bRet;
}
#else
int fds[2];
if (pipe(fds))
{
return false;
}
#endif
m_nWritePipe = fds[1];
//创建子线程base上下文(无锁)
if(bRet = (NULL != (ev_conf = event_config_new())))
{
if (bRet = (-1 != event_config_set_flag(ev_conf, EVENT_BASE_FLAG_NOLOCK)))
{
if (bRet = (NULL != (m_pBase = event_base_new_with_config(ev_conf))))
{
if (bRet = (NULL != (ev = event_new(m_pBase, fds[0], EV_READ | EV_PERSIST, pipe_process, this))))
{
if (bRet = (-1 != (event_add(ev, 0))))
{
bRet = (INVALID_HANDLE_VALUE != (m_hThread = (HANDLE)_beginthreadex( NULL, 0, &SubThreadEventDispatch, (void*)this, 0, NULL)))?true:false;
}
}
}
}
}
if(ev_conf)
event_config_free(ev_conf);
return bRet;
}
4、zzcTask类(基类),对接自己的具体业务,接收客户端消息:
(1)
#pragma once
class zzcTask
{
public:
zzcTask(void);
~zzcTask(void);
//初始化任务
virtual bool Init() = 0;
public:
//寄宿的子线程上下文
struct event_base *m_pBase;
//和客户端连接的描述符
int m_sock;
//寄宿线程的ID
int m_nThreadID;
};
#include "StdAfx.h"
#include "zzcTask.h"
zzcTask::zzcTask(void)
{
m_pBase = NULL;
m_sock = 0;
m_nThreadID = 0;
}
zzcTask::~zzcTask(void)
{
}
(2)子类
#pragma once
#include "zzctask.h"
class MyTask :public zzcTask
{
public:
MyTask(void);
~MyTask(void);
virtual bool Init();
};
#include "StdAfx.h"
#include "MyTask.h"
#include <event2/event.h>
#include <event2/bufferevent.h>
#include "iostream"
using namespace std;
MyTask::MyTask(void)
{
}
MyTask::~MyTask(void)
{
}
void EventCB(struct bufferevent *bev, short what, void *arg)
{
MyTask *pThis = (MyTask*)arg;
//如果对方网络断掉,或者机器死机有可能收不到BEV_EVENT_EOF数据
if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT))
{
bufferevent_free(bev);
if(pThis)
delete pThis,pThis = NULL;
}
}
static void ReadCB(bufferevent * bev, void *arg)
{
//接收客户端消息
}
bool MyTask::Init()
{
bufferevent *bev = bufferevent_socket_new(m_pBase, m_sock, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, ReadCB, 0, EventCB, this);
bufferevent_enable(bev, EV_READ | EV_WRITE);
//添加读超时
timeval t = {100,0};
bufferevent_set_timeouts(bev, &t, 0);
return true;
}