现在,我们开始一步步构建我们的项目了~
Master-Worker模式
本次一共涉及2个类:Master和Worker;
以下是两者的头文件:
/*************************************************************************
> File Name: server.h
> Author: Jiange
> Mail: jiangezh@qq.com
> Created Time: 2016年01月27日 星期三 19时33分00秒
************************************************************************/
#ifndef _MASTER_H
#define _MASTER_H
#include "worker.h"
#include <string>
#include "event2/event.h"
#include "event2/util.h"
class Master
{
public:
Master();
~Master();
bool StartMaster();
static void MasterExitSignal(evutil_socket_t signo, short event, void *arg); //SIGINT信号回调函数
static void MasterChldSignal(evutil_socket_t signo, short event, void *arg); //SIGCHLD信号回调函数
Worker worker;
struct event_base *m_base;
struct event *m_exit_event;
struct event *m_chld_event;
int nums_of_child; //子进程个数
};
#endif
/*************************************************************************
> File Name: worker.h
> Author: Jiange
> Mail: jiangezh@qq.com
> Created Time: 2016年01月27日 星期三 20时10分35秒
************************************************************************/
#ifndef _WORKER_H
#define _WORKER_H
#include <string>
#include <map>
#include "event2/event.h"
#include "event2/util.h"
#include "util.h"
class Master;
class Worker
{
public:
Worker();
~Worker();
void Run();
static void WorkerExitSignal(evutil_socket_t signo, short event, void *arg);
Master *master;
struct event_base *w_base;
struct event *w_exit_event;
std::string s_inbuf;
std::string s_intmp;
std::string s_outbuf;
};
#endif
具体实现:
/*************************************************************************
> File Name: master.cpp
> Author: Jiange
> Mail: jiangezh@qq.com
> Created Time: 2016年01月27日 星期三 19时37分23秒
************************************************************************/
#include "master.h"
#include "worker.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
Master::Master()
{
m_base = NULL;
m_exit_event = NULL;
m_chld_event = NULL;
nums_of_child = 4; //4个子进程
}
Master::~Master()
{
if (m_base)
{
event_free(m_exit_event);
event_free(m_chld_event);
event_base_free(m_base);
}
std::cout << "Master Closed" << std::endl;
}
bool Master::StartMaster()
{
std::cout << "Start Master" << std::endl;
worker.master = this;
//创建一定数量的worker
while (nums_of_child > 0)
{
switch (fork())
{
case -1:
return false;
case 0:
{
worker.Run(); //worker子进程入口
return true;
}
default:
--nums_of_child;
break;
}
}
//Master监听信号,一个用于退出,一个用于处理结束的子进程
m_base = event_base_new();
m_exit_event = evsignal_new(m_base, SIGINT, Master::MasterExitSignal, m_base);
m_chld_event = evsignal_new(m_base, SIGCHLD, Master::MasterChldSignal, this);
evsignal_add(m_exit_event, NULL);
evsignal_add(m_chld_event, NULL);
//开始事件循环
event_base_dispatch(m_base);
return true;
}
void Master::MasterExitSignal(evutil_socket_t signo, short event, void *arg)
{
//通知所有子进程。暂时不需要,因为程序不是守护进程。
//所有子进程都跟终端关联,都会收到SIGINT
//kill(0, SIGINT);
//结束事件循环
event_base_loopexit((struct event_base*)arg, NULL);
}
//防止子进程僵死,使用waitpid而不是wait->可能多个子进程同时关闭
void Master::MasterChldSignal(evutil_socket_t signo, short event, void *arg)
{
Master *master = (Master *)arg;
pid_t pid;
int stat;
while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
{
++(master->nums_of_child);
std::cout << "Child " << pid << " terminated" << std::endl;
}
}
/*************************************************************************
> File Name: worker.cpp
> Author: Jiange
> Mail: jiangezh@qq.com
> Created Time: 2016年01月28日 星期四 12时06分22秒
************************************************************************/
#include "worker.h"
#include "master.h"
#include <stdlib.h>
#include <iostream>
Worker::Worker()
{
master = NULL;
w_base = NULL;
w_exit_event = NULL;
}
Worker::~Worker()
{
if (w_exit_event)
event_free(w_exit_event);
if (w_base)
event_base_free(w_base);
std::cout << "Worker closed" << std::endl;
}
void Worker::Run()
{
w_base = event_base_new();
w_exit_event = evsignal_new(w_base, SIGINT, Worker::WorkerExitSignal, w_base);
evsignal_add(w_exit_event, NULL);
event_base_dispatch(w_base);
return;
}
void Worker::WorkerExitSignal(evutil_socket_t signo, short event, void *arg)
{
event_base_loopexit((struct event_base*)arg, NULL);
}
这样子,一个简单的“Master-Worker模式”就完成了。
测试入口:
/*************************************************************************
> File Name: main.cpp
> Author: Jiange
> Mail: jiangezh@qq.com
> Created Time: 2016年01月27日 星期三 19时29分26秒
************************************************************************/
#include "master.h"
#include <iostream>
int main(int argc, char * argv[])
{
Master master;
std::cout << "----Slighttpd----" << std::endl;
if (!master.StartMaster())
return -1;
std::cout << "----Goodbye----" << std::endl;
return 0;
}
需要注意的几个点:
Master和Worker所做的事情是不同的,因此两者均有自己独立的event_base;
worker的event_base_new()需要在run()函数中使用(在fork之后),而不能在构造函数中初始化时分配(fork之前)。否则,好像4个子进程将共用同一个event_base。(Q:按理来说fork应该是完全复制过来的,为什么会共用同一个呢?可能是跟libevent的实现方式有关?)
接下来,我们需要对它进行拓展,以后将在Master中加入插件相关的内容,在Worker中加入监听者Listener和连接者Connection。