• 典型服务器模型


    ibevent:

    reactor反应堆模型:

    关键部分:

    1) 事件源
    Linux上是文件描述符,Windows上就是Socket或者Handle了,这里统一称为“句柄集”;程序在指定的句柄上注册关心的事件,比如I/O事件。

    2) event demultiplexer——事件多路收集和分发机制(其实就是epoll等,直接运用在reactor中)
    由操作系统提供的I/O多路复用机制,比如select和epoll。
    程序首先将其关心的句柄(事件源)及其事件注册到event demultiplexer上;
    当有事件到达时,event demultiplexer会发出通知“在已经注册的句柄集中,一个或多个句柄的事件已经就绪”;
    程序收到通知后,就可以在非阻塞的情况下对事件进行处理了。
    对应到libevent中,依然是select、poll、epoll等,但是libevent使用结构体eventop进行了封装,以统一的接口来支持这些I/O多路复用机制,达到了对外隐藏底层系统机制的目的。

    3) Reactor——反应器
    Reactor,是事件管理的接口,内部使用event demultiplexer注册、注销事件;并运行事件循环,当有事件进入“就绪”状态时,调用注册事件的回调函数处理事件。
    对应到libevent中,就是event_base结构体。
    一个典型的Reactor声明方式

    class Reactor
    {
    public:
        int register_handler(Event_Handler *pHandler, int event);
        int remove_handler(Event_Handler *pHandler, int event);
        void handle_events(timeval *ptv);
        // ...
    };
    View Code

    4) Event Handler——事件处理程序,(注意,事件处理函数是一个整体,这个整体可以注册,跟事件绑定在一起,换句话说,这个事件处理函数类,声称对这个事件感兴趣(所谓的事件,就是读写事情等等)
        事件处理程序提供了一组接口,每个接口对应了一种类型的事件,供Reactor在相应的事件发生时调用,执行相应的事件处理。通常它会绑定一个有效的句柄。
    对应到libevent中,就是event结构体。
    下面是两种典型的Event Handler类声明方式,二者互有优缺点。

    class Event_Handler
    {
    public:
        virtual void handle_read() = 0;
        virtual void handle_write() = 0;
        virtual void handle_timeout() = 0;
        virtual void handle_close() = 0;
        virtual HANDLE get_handle() = 0;
        // ...
    };
    class Event_Handler
    {
    public:
        // events maybe read/write/timeout/close .etc
        virtual void handle_events(int events) = 0;
        virtual HANDLE get_handle() = 0;
        // ...
    };
    View Code

    然后就在reactor中不停的循环wait_epoll,这利用demultiplexer中函数进行,同时reactor的hanle_events是(当事件源就绪的时候,回调之前注册过的时间处理函数)通过转接demultiplexer中的函数,由于,得到的就绪的fd,可以得使他就绪的事件,根据handle和事件处理函数之间的关系,通过map存储,这样就可以得到注册的事件处理函数,然后又根据事件类型(写还是读),调用事件处理类中的对应函数

    每个事件处理类,对应一个handle,但是一个同样的handle可以跟多个事件处理类对应(不同时刻)。这个handle有aceept生成。

    int ReactorImplementation::RegisterHandler(EventHandler * handler, event_t evt)    //参数是事件处理类和事件,但是通过事件处理类中的GetHandle()函数得到事件处理类对应的handle事件源。然后进行handle和事件处理类之间的对应关系的     {                                                                                                                       // map
    handle_t handle = handler->GetHandle();
    std::map<handle_t, EventHandler *>::iterator it = m_handlers.find(handle);
    if (it == m_handlers.end())
    {
    m_handlers[handle] = handler;
    }
    return m_demultiplexer->RequestEvent(handle, evt);
    }

    map<handle_t, EventHandler *>  m_handlers;//可知道socket描述符和事件处理类有一对一的关系。。wait_epoll得到就绪的fd还有引发fd就绪的事件,就可以回调当初与事件绑定的事件处理类(回调)

    每个fd都有相应事件,如果对应fd上面的事件就绪,就返回fd,又因为注册的时候,事件是跟事件处理类对应的,事件处理类声称对事件感兴趣。所以可以根据,fd找到对应的就绪事件,然后回调事件处理类。注册事件的函数的参数是fd类型和事件处理类类型。

  • 相关阅读:
    第五章 面向方面编程___通知类型
    从 C++ 到ObjectiveC
    iPhone/Mac ObjectiveC内存管理教程和原理剖析(三)@property (retain)和@synthesize的默认实现
    两个操作字符串的方法:读取指定位置的字符和找出某个字符串的位置
    SQLITE3使用总结
    iphone中如何进行多线程编程
    sqlite数据库在IOS中的运用
    重载、覆盖、隐藏
    (转)c/c++ 内存管理
    iPhone/Mac ObjectiveC内存管理教程和原理剖析(四)系统自动创建新的autorelease pool
  • 原文地址:https://www.cnblogs.com/kkshaq/p/4451939.html
Copyright © 2020-2023  润新知