该项目是一款在线棋牌对战平台,已实现用户登录、注册、游戏下载、游戏删除。内置在线五子棋游戏,并实现创建房间,加入房间,快速匹配,好友对战,掉线重连,人机对战等功能。
启动游戏
在线游戏大厅界面
对局准备界面
对局结束界面
C/S架构,客户端采用qt开发GUI界面,服务端在linux平台开发
服务器采用基于epoll监听的Reactor模式处理客户端请求
Reactor主要由Reactor 线程、
Handlers 处理器组成,Reactor线程负责监听客户端请求,通过执行epoll_wait判断客户端事件是否到达,如果有事件到达,将该事件绑定到一个Handler处理器,则将该任务放入事件队列,线程池的工作者线程从任务队列中获取线程。
//事件监听循环代码
void Block_Epoll_Net::EventLoop()
{
printf("EventLoop:server running\n");
int i = 0;
while (1) {
/* 等待事件发生 */
int nfd = epoll_wait( m_epoll_fd, events, MAX_EVENTS+1, 1000);
if (nfd < 0) {
printf("epoll_wait error, exit\n");
continue;
}
for (i = 0; i < nfd; i++) {
struct myevent_s *ev = (struct myevent_s *)events[i].data.ptr;
int fd = ev->fd;
if ( (events[i].events & EPOLLIN) ) {
if( fd == m_listenfd )
accept_event();//accept事件
else
recv_event( ev );//客户端业务事件
}
if ((events[i].events & EPOLLOUT) ) {
epollout_event( ev );
}
}
}
}
消费者线程进行任务处理
/* 工作线程函数 消费者*/
void * thread_pool::Custom(void * arg)
{
// 获取线程池对象指针
pool_t * p = (pool_t*)arg;
task_t task;
while(p->thread_shutdown) // 线程池未关闭
{
pthread_mutex_lock(&p->lock);// 上锁
// 当前任务队列中没有任务,且线程池未关闭
while(p->queue_cur == 0 && p->thread_shutdown )
{
// 等待有新的任务被添加到队列中
pthread_cond_wait(&p->not_empty,&p->lock);
}
// 线程池已关闭
if(!p->thread_shutdown )
{
pthread_mutex_unlock(&p->lock);
pthread_exit(NULL); // 结束此线程
}
// 需要等待关闭的线程数大于零,且当前存活的线程数大于最小线程数
if(p->thread_wait > 0 && p->thread_alive > p->thread_min)
{
--(p->thread_wait); // 等待关闭的线程数减一
--(p->thread_alive);// 存活的线程数减一
pthread_mutex_unlock(&p->lock);// 解锁
pthread_exit(NULL);// 结束此线程
}
// 取出任务
task.task = p->queue_task[p->queue_rear].task;
task.arg = p->queue_task[p->queue_rear].arg;
p->queue_rear = (p->queue_rear + 1) % p->queue_max;// 更新队列尾指针
--(p->queue_cur);// 当前任务队列中的任务数减一
pthread_cond_signal(&p->not_full); // 通知生产者线程有新的任务可供添加
++(p->thread_busy);// 忙碌的线程数加一
pthread_mutex_unlock(&p->lock);// 解锁
//执行核心工作
(*task.task)(task.arg);
pthread_mutex_lock(&p->lock);// 上锁
--(p->thread_busy);// 忙碌的线程数减一
pthread_mutex_unlock(&p->lock); // 解锁
}
return 0;
}