libevent

作者: 何亮hook_8285 | 来源:发表于2022-10-05 16:18 被阅读0次

    概念

    libevent是基于事件驱动的网络框架库,它的事件分为:网络事件、定时器事件、信号事件等,所有的事件触发都由事件分发器统一触发。

    使用步骤

    1.创建事件基类(event_base),它用来管理所有事件信息。

    2.创建网络连接监听事件(evconnlistener),它可监听socket连接。

    3.创建读写事件(bufferevent),它用来接收读写数据事件触发。

    4.创建数据事件(evbuffer),它可以获取读写数据。

    5.开启事件分发(event_base_dispatch),它负责分发事件信息。

    引入头文件

    //引入头文件
    #include <winsock2.h>
    #include <windows.h>
    
    #include <event2/event.h>
    #include <event2/listener.h>
    #include <event2/buffer.h>
    #include <event2/bufferevent.h>
    
    #ifndef _WIN32
    #include <signal.h>
    #endif
    

    常用函数

    //创建事件基类
    struct event_base *event_base_new(void);
    
    //创建服务端的监听配置
    //flags 可设置LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|LEV_OPT_THREADSAFE
    struct evconnlistener *evconnlistener_new(struct event_base *base,
        evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
        evutil_socket_t fd)
        
    //设置非阻塞
    int evutil_make_socket_nonblocking(evutil_socket_t sock);
    
    //创建127.0.0.1回环通讯
    int evutil_socketpair(int d, int type, int protocol, evutil_socket_t sv[2]);
    
    //重复复用
    int evutil_make_listen_socket_reuseable(evutil_socket_t sock);
    
    //端口重复复用
    int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock)
        
    //绑定ipv6
    int evutil_make_listen_socket_ipv6only(evutil_socket_t sock);
    
    
    //关闭close
    int evutil_closesocket(evutil_socket_t sock);
    //开启监听
    int event_listener_enable(struct evconnlistener *lev)
    //停止监听    
    int event_listener_disable(struct evconnlistener *lev)
    //获取监听中的事件对象    
    event_base *evconnlistener_get_base(struct evconnlistener *lev)    
    //设置监听回调
    void evconnlistener_set_cb(struct evconnlistener *lev,evconnlistener_cb cb, void *arg)
    //销毁监听
    void evconnlistener_free(struct evconnlistener *lev);
    //创建读写缓存对象
    bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd,int options)
        
    //连接服务器并且创建读写缓存
    int bufferevent_socket_connect(struct bufferevent *bufev, const struct sockaddr *addr, int socklen);
    
    //获取读写对象中的事件对象
    event_base *bufferevent_get_base(struct bufferevent *bev)
    
    //设置读写回调
    void bufferevent_setcb(struct bufferevent *bufev,bufferevent_data_cb readcb, bufferevent_data_cb writecb,bufferevent_event_cb eventcb, void *cbarg)
    
    //触发写事件
    int bufferevent_write(struct bufferevent *bufev,const void *data, size_t size);
    
    
    
    //从读取事件对象中读取输入的缓存数据
    size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
        
    //从读写事件中获取输入缓存
    evbuffer *bufferevent_get_input(struct bufferevent *bufev)
    
    //从读写事件中获取输出缓存
    evbuffer *bufferevent_get_output(struct bufferevent *bufev)
    
    //开启读写事件
    int bufferevent_enable(struct bufferevent *bufev, short event)
    //关闭读写事件
    int bufferevent_disable(struct bufferevent *bufev, short event)
    //销毁读写事件
    void bufferevent_free(struct bufferevent *bufev);
    
    //获取读写事件的状态
    short bufferevent_get_enabled(struct bufferevent *bufev)
        
    //设置读写事件的超时时间
    int bufferevent_set_timeouts(struct bufferevent *bufev,const struct timeval *timeout_read, const struct timeval *timeout_write)
    
    //读写事件的高低水位
    void bufferevent_setwatermark(struct bufferevent *bufev, short events,
        size_t lowmark, size_t highmark)
        
    //读写事件的高低水位的状态
    int bufferevent_getwatermark(struct bufferevent *bufev, short events,
        size_t *lowmark, size_t *highmark);
    
    //读写事件加锁
    void bufferevent_lock(struct bufferevent *bufev)
    
    //读写事件解锁
    void bufferevent_unlock(struct bufferevent *bufev);
    
    //读写事件加引入
    void bufferevent_incref(struct bufferevent *bufev)
    //读写事件减引入
    int bufferevent_decref(struct bufferevent *bufev)  
    
    //刷新事件缓存
    int bufferevent_flush(struct bufferevent *bufev,
        short iotype,
        enum bufferevent_flush_mode mode)
        
    //读写事件增加过滤器
    struct bufferevent *bufferevent_filter_new(struct bufferevent *underlying,
                   bufferevent_filter_cb input_filter,
                   bufferevent_filter_cb output_filter,
                   int options,
                   void (*free_context)(void *),
                   void *ctx);    
    
    //创建缓存
    evbuffer *evbuffer_new(void)
    
    //销毁缓存
    void evbuffer_free(struct evbuffer *buf)
    //设置读缓存最大数
    int evbuffer_set_max_read(struct evbuffer *buf, size_t max) 
    //获取缓存最大数
    size_t evbuffer_get_max_read(struct evbuffer *buf)    
    //缓存开启锁
    int evbuffer_enable_locking(struct evbuffer *buf, void *lock)
    
    //缓存锁
    void evbuffer_lock(struct evbuffer *buf)
    
    //缓存解锁
    void evbuffer_unlock(struct evbuffer *buf)   
    
    //获取缓存数据长度
    size_t evbuffer_get_length(const struct evbuffer *buf)
    
    //扩展缓存的容量
    int evbuffer_expand(struct evbuffer *buf, size_t datlen)
        
    //复制缓存中的数据到另一个指针对象中
    ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen);    
    
    //删除缓存中的数据,并且生成一个新的指针数据
    int evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
        size_t datlen)
        
    //读取一行数据
    /***
    enum evbuffer_eol_style {
        EVBUFFER_EOL_ANY,            // 任意数量的\r和\n
        EVBUFFER_EOL_CRLF,           // \r或者\r\n
        EVBUFFER_EOL_CRLF_STRICT,    // \r\n
        EVBUFFER_EOL_LF,             // \n
        EVBUFFER_EOL_NUL             // \0
    };
    ***/
    char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out,
        enum evbuffer_eol_style eol_style)
    
    //将源缓存数据添加到目标缓存中
    int evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
        
    //将buffer中的数据指向到指针中
    int evbuffer_prepend(struct evbuffer *buf, const void *data, size_t size); 
    //事件循环
    int event_base_dispatch(struct event_base *);
    //销毁事件
    void event_base_free(struct event_base *)
    
    //通过监听对象获取文件描述符
    evutil_socket_t evconnlistener_get_fd(struct evconnlistener *lev)
        
    //创建事件    
    event *event_new(struct event_base *, evutil_socket_t, short, event_callback_fn, void *) 
    
    //添加事件
    int event_add(struct event *ev, const struct timeval *timeout);
    //消费事件
    void event_free(struct event *)
      
    //宏函数,添加定时器事件
    evtimer_add(ev, tv)
    //删除定时器事件    
    evtimer_del(ev) 
    
        
    

    创建管道的代码

    #ifdef _WIN32
        evutil_socket_t fds[2];//0读文件描述符,1写的文件描述符
        if(evutil_socketpair(AF_INET,SOCK_STREAM,0,fds)<0)
        {
            std::cout << "create evutil_socketpair channel failed" << std::endl;
            return false;
        }
        evutil_make_socket_nonblocking(fds[0]);
        evutil_make_socket_nonblocking(fds[1]);
    #else
        int fds[2]; //0读文件描述符,1写的文件描述符
        if(pipe(fds))
        {
            std::cout << "create pipe failed " << std::endl;
            return false;
        }
    #endif
    int notifySendFd_=fds[1];
    
    event_config *ev_config=event_config_new();
    //EVENT_BASE_FLAG_NOLOCK 设置非锁模式
    event_config_set_flag(ev_config,EVENT_BASE_FLAG_NOLOCK);
    event_base *base_=event_base_new_with_config(ev_config);
    event_config_free(ev_config);
    
    if(!this->base_)
    {
        std::cerr << "event_base_new_with_config failed in thread" << std::endl;
        return false;
    }
    
    event *ev = event_new(this->base_, fds[0], EV_READ | EV_PERSIST, NotifyCB, this);
    event_add(ev, 0);
    return false;
    

    客户端连接

    #ifdef _WIN32
      WSADATA wsa;
      WSAStartup(MAKEWORD(2,2),&wsa);
    #else
    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
     return 1;
    #endif
    
    sockaddr_in sockaddrIn;
    sockaddrIn.sin_family=AF_INET;
    sockaddrIn.sin_port=htons(9988);
    evutil_inet_pton(sockaddrIn.sin_family, "127.0.0.1", (void *)&sockaddrIn.sin_addr);
    event_base *base=event_base_new();
    bufferevent *bev=bufferevent_socket_new(base,-1,BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bev, ReadClient, WriteClient, EventClient, 0);
    bufferevent_enable(bev, EV_WRITE | EV_READ);
    bufferevent_socket_connect(bev,(sockaddr*)&sockaddrIn,sizeof(sockaddrIn));
    event_base_dispatch(base);
    event_base_free(base);
    
    #ifdef _WIN32
        WSACleanup();
    #endif
    

    启动服务端

        event_base * base = event_base_new();
        if (base)
        {
            cout << "event_base_new success!" << endl;
        }
        sockaddr_in sin;
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(9988);
    
        evconnlistener *ev = evconnlistener_new_bind(base,
                                                     listen_cb,
                                                     base,
                                                     LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,
                                                     10,
                                                     (sockaddr*)&sin,
                                                     sizeof(sin)
        );
    
        //事件分发处理
        if(base)
            event_base_dispatch(base);
        if(ev)
            evconnlistener_free(ev);
        if(base)
            event_base_free(base);
    #ifdef _WIN32
        WSACleanup();
    #endif
    

    定时器

    event_base *base=event_base_new();
    event* ev1 =event_new(base,-1,EV_PERSIST,timer2,0);
    timeval t1 = { 5,0 };
    evtimer_add(ev1, &t1);
    event_base_dispatch(base);
    

    相关文章

      网友评论

          本文标题:libevent

          本文链接:https://www.haomeiwen.com/subject/ykiuartx.html