libevent

2022-10-05  本文已影响0人  何亮hook_8285

概念

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);
上一篇下一篇

猜你喜欢

热点阅读