Reactor模型简介

前端之家收集整理的这篇文章主要介绍了Reactor模型简介前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

服务器编程需要处理大量链接,reactor模型是一种高效的事件处理模型,常常用于处理这种问题,其核心是一个不断查询的循环,查询多个可能发生事件的事件源

while(true)
{
    //查询事件源是否有事件
}

为了同时能够处理大量链接,一般会使用多路复用I/O来监听,比如epoll或select。

while(true)
{
    int ret = select(&read_fds,&write_fds,&exp_fds,NULL);
}

监听到准备好的I/O事件之后就需要分别处理掉,也就是所谓的分发,毕竟读任务,写任务,异常都需要不同的处理。

while(true)
{
    int ret = select(&read_fds,NULL);
    //封装成任务,分发出去处理
}

比如什么都不做,只是出现读读写写处理异常的形式

while(true)
{
    int ret = select(&read_fds,NULL);
    for_each(fd in read_fds)
    {
        do_read(fd);
    }
    for_each(fd in write_fds)
    {
        do_write(fd);
    }
    for_each(fd in exp_fds)
    {
        do_excep(fd);
    }
}

通常在do_*函数里面就干自己想要处理的动作。
在每一次 while(true) 循环的最后会清理掉已经发生过事件的事件源,并重新注册下一次需要监听的事件源。因此在do_*函数里面最后一件事情就是决定还要不要继续监听这次处理过的fd,也既是重新注册回去。

while(true)
{
    int ret = select(&read_fds,NULL);
    //封装成分发任务,分发出去处理
    clear(&read_fds,&exp_fds);
    re_register();
}

用epoll的ET模式会省事儿很多,触发一次之后就不再触发,除非再次注册

while(true)
{
    int ret = epoll_wait(epoll_fd,events,MAX_EVENTS,-1);
    for(int i = 0; i < ret; ++i)
    {
        if(events[i].fd == listenfd)
        {
            //添加新进入的socket
        }
        if(events[i].events & EPOLLIN)
        {
            //读数据,然后封装成任务分发处理
        }
        else if(events[i].events & EPOLLOUT)
        {
            //写数据
        }
    }
}

void process()
{
    //处理数据
    epoll_ctl(epoll_fd,EPOLL_CTL_DEL,fd,0 );
    //or epoll_ctl(epoll_fd,EPOLL_CTL_MOD,&event );
    //or epoll_ctl(epoll_fd,EPOLL_CTL_ADD,&event );
}

单线程的reactor分发后的处理也在同一个线程中,需要处理比较迅速,绝对不能阻塞,否则整个事件循环就阻塞了,这是个悲剧。
多线程的reactor会将任务分发到不同的线程中去处理,最大化利用多核cpu。可以利用线程池来管理这些线程,线程池持有一个任务队列,各个线程竞争的从任务队列里面领取任务来处理。在多个线程中调用epoll_ctl和epoll_wait是线程安全的。

更多学习:
C语言reactor模式参考libevent
python语言reactor模式参考twisted

参考资料:
《Linux高性能服务器编程》
http://www.cnblogs.com/hustcat/archive/2012/01/11/2319249.html

原文链接:https://www.f2er.com/react/308029.html

猜你在找的React相关文章