概念
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);
网友评论