实现一个Reactor框架,Reactor是一种事件驱动框架,该框架下改变了select、poll和epoll对fd进行管理的思路转变成对读写事件进行管理,重点变成了事件。Reator逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,在相应的时间发生,Reator将主动调用这些接口函数,即回调函数
reactor以epoll为底层,主要是对事件为基本单元进行处理,多个事件并发地交给服务器进行处理,服务器将传入的事件同步地分派给相关地处理函数,reactor处理事件模型如下所示
首先分别定义了两个结构体,一个是事件 结构体ntyevent,一个是reactor结构体ntyreactor
ntyevent
* 该事件的fd
* 对应的事件类型events比如输入输出
* 需要传给回调函数的参数,一般传的是该事件所属reactor的指针void* arg
* 对应的回调函数指针 int (*callback)
* 事件是否创建的状态 status
* 事件消息的buffer
* 消息长度length
* 最后的运行时间last_active
ntyreactor(通过reactor来管理所有的事件)
* 该reactor的fd
* 该reactor内部的ntyevent数组==*events==(运行时通过epoll_wait取出所有存在内核的事件)
//事务结构体
//缓冲区长度
#define BUFFER_LENGTH 4096
// epoll中的事物数量
#define MAX_EPOLL_EVENT 1024
#define SERVER_PORT 8888
struct ntyevent
{
int fd; //事务的fd
int events; // epoll events类型
void *arg; //需要传给回调函数的参数,一般传的是reactor的指针
int (*callback)(int fd, int events, void *arg); //对应的回调函数
int status; // 0:新建 1:已存在
char buffer[BUFFER_LENGTH];
int length;
long last_active;
};
// reator使用的结构体
struct ntyreactor
{
int epfd; // reatctor的fd
struct ntyevent *events; // reactor管理的基础单元
};
int recv_cb(int fd, int events, void *arg);
int send_cb(int fd, int events, void *arg);
int accpet_cb(int fd, int events, void *arg);
void nty_event_set(struct ntyevent *ev, int fd, NCALLBACK callback, void *arg);
int nty_event_add(int epfd, int events, struct ntyevent *ev);
int nty_event_del(int epfd, struct ntyevent *ev);
//设置ntyevent的参数
void nty_event_set(struct ntyevent *ev, int fd, NCALLBACK callback, void *arg)
{
ev->fd = fd;
ev->callback = callback;
ev->events = 0;
ev->arg = arg;
ev->last_active = time(NULL);
return;
}
//增加或修改
int nty_event_add(int epfd, int events, struct ntyevent *ev)
{
//使用的是linux内核里的epoll
struct epoll_event ep_ev = {
0, {
0}};
//这一步非常关键传到联合体data的ptr里的是ntyevent指针
ep_ev.data.ptr = ev;
ep_ev.events = ev->events = events;
//判断该事件是否已经添加过
int op;
if (ev->status == 1)
{
op = EPOLL_CTL_MOD;
}
else
{
op = EPOLL_CTL_ADD;
ev->status = 1;
}
// epoll_ctl进行对应操作
if (epoll_ctl(epfd, op, ev->fd, &ep_ev) < 0)
{
printf("event add failed [fd=%d], events[%d]\n", ev->fd, events);
return -1;
}
return 0;
}
int nty_event_del(