C language simple Reactor

Reactor

Introduction

There are many online Reactor pattern to explain, I do not want to introduce too much here. There are three core.

  1. Abstract event
  2. Multiple event dispatcher
  3. A Reactor for managing the entire process

reactor by c

Reactor is we extract from the code out to facilitate our management. But here we leave it entirely. Very violent use of process-oriented thinking to do.

  • Abstract event - directly into our specific fd
  • Multiple event dispatcher - directly into our specific epoll

Code ideas

General settings server. socket-bind-listen, but to pay attention set to become nonblock.

Now we get listenfd. We hope that when a customer is connected arrival, which automatically helps us to accept_conn callback function. what can we do about it?

With epoll

The role of epoll when the file descriptor is ready to inform the user of the epoll file descriptor is ready.
It is obvious that we will listenfd registered to epoll when there are connections come, we will notify epoll listenfd ready. According to previous ideas, we will do if a judgment, if fd is returned listenfd went to call accept_conn. If other fd, just do something else.

But here we will use the idea of ​​a callback function. When there is an event-ready (that is fd-ready time), we no brain function call_back called a callback. (Obviously, this is a function pointer)

        int nfd = epoll_wait(g_efd, events, MAX_EVENTS + 1, 1000);
        my_error(nfd, "epoll_wait error");
        for(i = 0; i < nfd; ++i)
        {
            struct myevent_s *ev = (struct myevent_s *)events[i].data.ptr;
            if((events[i].events & EPOLLIN) && (ev->events & EPOLLIN))
                ev->call_back(ev->fd, events[i].events, ev->arg);
            if((events[i].events & EPOLLOUT) && (ev->events & EPOLLOUT))
                ev->call_back(ev->fd, events[i].events, ev->arg);
        }

Abstract event

Here I think the nature of the teacher Ge said a word, the state of the program is to inform and transform messages. So simply to express the state of the event with fd longer enough.
We need a structure as follows.

typedef void (*Callback_t)(int , int , void*);
struct myevent_s{
    int fd;
    int events; // 记录所关怀的事件类型,读事件还是写事件
    Callback_t call_back; // 回调函数
    void *arg; // 指向自己的指针
    int status; // 记录自己是否在epoll树上
    char buf[BUFFLEN]; // 一个缓冲区
    int len; // 缓冲区有效数据的长度
    //long last_active; 暂时忽略
};

Over the first four data structure it must have before. After a few more features to help complete.

listenevent

We want to make listenfd listenevent. Under our list of things to do, you will understand why we want to set the event of such a structure.

  1. listenfd the fd value is bound to save.
  2. listenfd to be added to the epoll, is concerned about the event read or write event? - you need to set the event.
  3. When listenfd ready, that is a callback function. To record the address of that function. - you need to set call_back.
  4. When listenfd ready, we want to return the pointer to the event ready event immediately. So that we can go to the callback its members through a pointer.
typedef union epoll_data{
    void *ptr;
    int fd;
    uint32_t u32;
    uint64_t u64;
}epoll_data_t;
struct epoll_event{
    _uint32_t events;
    epoll_data_t data;
};

data is a consortium, we often use is the fd member, this time we use ptr members. Register it to the epoll. So that when fd ready. We will get through this pointer event event.

If you do not understand how arg point to themselves, look at the following pseudo-code.

// 伪代码
void accept_conn(...)
{...}
event_set()
{
listen_event.fd = listenfd;
listen_event.event = EPOLLIN;
listen_event.call_back = accept_conn;
listen_event.arg = &listen_event;
}

accept_conn

Now whenever a connection arrives, it will call back to accept_conn in the past. We can get through connfd accept.
The next step is to connfd packaged again into an event registered in the epoll. With the above using the experience of events, we can easily write event handling code to read and write logic.

github

My github

to sum up

These are the simple use c to achieve Reactor, the next I'll use c ++ to achieve, and abstract Reactor core in three classes. Reactor also muduo and the basic idea of ​​libevent. If interested, you can read the source libevent library.

Guess you like

Origin blog.csdn.net/weixin_43468441/article/details/93775965
Recommended