官方网站:libevent官方网站
相关资源:libevent相关资源
百度网盘链接:https://pan.baidu.com/s/17LeA3aGxgU7QUUFBt7zfpw
提取码:0ae7
struct event_base *event_base_new(void);
struct event_base *base =event_base_new();
//常规事件event
event_new();
//带缓冲区的事件bufferevent
bufferevent_socket_new();
int event_add(struct event *ev, const struct timeval *tv);
int event_base_dispatch(struct event_base *base);
event_base_dispatch(base);
event_base_free(base);
struct event *ev;
struct event *event_new(struct event_base *base,evutil_socket_t fd,short what,event_callback_fn cb; void *arg);
参数:
base: event_base_new()返回值
fd: 绑定到 event 上的文件描述符
what:对应的事件(r、w、e)
EV_READ 一次读事件
EV_WRTIE 一次写事件
EV_PERSIST 持续触发。 结合 event_base_dispatch 函数使用,生效。
cb:一旦事件满足监听条件,回调的函数
typedef void (*event_callback_fn)(evutil_socket_t fd, short, void *)
arg: 回调的函数的参数
返回值:成功创建的 event
int event_add(struct event *ev, const struct timeval *tv);
参数:
ev: event_new() 的返回值。
tv:NULL(不会超时)
int event_free(struct event *ev);
ev: event_new() 的返回值。
从event_base上删除事件【了解】
int event_del(struct event *ev);
ev: event_new() 的返回值。
未决事件:有资格被处理,但尚未被处理
#include
bufferevent有两个缓冲区,队列实现,数据只能读一次
读缓冲:读取了任意量的数据之后会调用读回调函数,使用bufferevent_read()函数从读缓冲区读取数据。
写缓冲:bufferevent_write()函数向写缓冲中写入数据,写缓冲一旦有数据就会自动刷新,将数据发送给对端,写完后调用写回调函数。
struct bufferevent *bufferevent_socket_new(
struct event_base *base,
evutil_socket_t fd,
enum bufferevent_optionsoptions);
参数:
base:event _base
fd:封装到bufferevent的文件描述符
options:BEV_OPT_CLOSE_ON_FREE:释放 bufferevent 时关闭底层传输端口。这将关闭底层套接字,释放底层 bufferevent 等。
返回:
成功:函数返回一个 bufferevent
失败:返回 NULL
void bufferevent_free(struct bufferevent *bev);
bufferevent_setcb()函数修改 bufferevent 的一个或者多个回调
void bufferevent_setcb(
struct bufferevent *bufev,
bufferevent_data_cb readcb,
bufferevent_data_cb writecb,
bufferevent_event_cb eventcb,
void *cbarg);
参数:
bufev: bufferevent_socket_new() 返回值
readcb: 设置bufferevent 读缓冲,对应回调 read_cb{ bufferevent_read() 读数据 }
writecb: 设置bufferevent 写缓冲,对应回调 write_cb { } ,给调用者,发送写成功通知。可以 NULL
eventcb: 设置事件回调。也可传NULL
cbarg:上述回调函数使用的参数。
readcb对应回调函数【从bufferevent的输入缓冲区移除数据】
typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx);
读数据:从bufferevent输入缓冲区中移除数据(队列)
size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
writecb对应回调函数【向bufferevent的输出缓冲区添加数据】
int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size);
bufferevent_write()将内存中从 data 处开 始的 size 字节数据添加到输出缓冲区的末尾
int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf);
bufferevent_write_buffer()移除 buf 的所有内 容,将其放置到输出缓冲区的末尾
eventcb对应回调函数
typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short events, void *ctx);
BEV_EVENT_READING:读取操作时发生某事件,具体是哪种事件请看其他标志。
BEV_EVENT_WRITING:写入操作时发生某事件,具体是哪种事件请看其他标志。
BEV_EVENT_ERROR : 操 作 时 发 生 错 误 。 关 于 错 误 的 更 多 信 息 , 请 调 用
EVUTIL_SOCKET_ERROR()。
BEV_EVENT_TIMEOUT:发生超时.
BEV_EVENT_EOF:遇到文件结束指示。
BEV_EVENT_CONNECTED:请求的连接过程已经完成。
void bufferevent_enable(struct bufferevent *bufev, short events) ;//启用
void bufferevent_disable(struct bufferevent *bufev, short events) ;//禁用
short bufferevent_get_enabled(struct bufferevent *bufev);//获取缓冲区禁用状态
events:EV_READ、EV_WRITE 或者 EV_READ | EV_WRITE
默认:write 缓冲是 enable、read 缓冲是 disable,调用函数开启读缓冲
客户端:
int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen);
bev:bufferevent事件对象(封装了fd)
address 和 addrlen 参数跟标准调用 connect()的参数相同
【注】:如果使用 bufferevent_socket_connect() 发起连接,将只会收到 BEV_EVENT_CONNECTED 事件。如果自己调用 connect(),则连接上将被报告为写入事件。
#include
evconnlistener_new*()函数分配和返回一个新的连接监听器对象
struct evconnlistener * evconnlistener_new(
struct event_base *base
evconnlistener_cb cb,
void *ptr,
unsigned flags,
int backlog ,
evutil_socket_t fd);
evconnlistener_new_bind(
struct event_base *base,
evconnlistener_cb cb,
void *ptr,
unsigned flags,
int backlog ,
const struct sockaddr *sa,
int socklen);
参数:
cb:监听回调函数,一旦回调,内部与客户端连接完成,进行数据通信
ptr:传递给回调函数
flags:“可识别的标志”
LEV_OPT_CLOSE_ON_FREE :如果设置了这个选项,释放连接监听器会关闭底层套接字
LEV_OPT_REUSEABLE :端口复用
backlog:任何 时刻网络栈允许处于还未接受状态的最大未决连接数。-1:表示使用默认最大值
sa:服务器的地址结构
socklen:地址结构大小
返回:成功创建的监听器
释放监听器
void evconnlistener_free(struct evconnlistener *lev);
回调函数类型
typedef void (*evconnlistener_cb)(
struct evconnlistener *listener,
evutil_socket_t sock,
struct sockaddr *addr,
int len,
void * ptr);
参数:
listener:接收连接的连接监听器
sock:用于通信的文件描述符
addr:客户端地址结构
len:客户端地址结构的长度
ptr:调用 evconnlistener_new() 时用户提供的指针
【注】:该回调函数由框架自动调用
创建event_base
创建bufferevent事件对象,调用bufferevent_socket_new()函数
使用bufferevent_setcb() 函数给 bufferevent的 read、write、event 设置回调函数
当监听的事件满足时,read_cb会被调用,在其内部 bufferevent_read()读取数据
使用 evconnlistener_new_bind 创建监听服务器, 设置其回调函数,当有客户端成功连接时,这个回调函数会被调用
在函数内部封装 listner_cb() 函数。完成与客户端通信
启动循环event_base_dispatch()
设置读写缓冲的使能状态
释放连接
创建event_base
创建一个用于跟服务器通信的bufferevent事件对象,调用bufferevent_socket_new()函数
与服务器建立连接,调用bufferevent_socket_connect()函数
使用bufferevent_setcb() 函数给 bufferevent的 read、write、event 设置回调函数
设置读写缓冲的使能状态
接收、发送数据,bufferevent_read()、bufferevent_write()
启动循环监听event_base_dispatch()
释放连接
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//读缓冲区回调
void read_cb(struct bufferevent *bev, void *data)
{
char buf[1024]={0};
//读取数据
bufferevent_read(bev,buf,sizeof(buf));
cout<<"client:"<<buf<<endl;
char *p="I am server,I have received your data";
//写数据给客户端 给bufferevent写缓冲写数据,写缓冲将数据刷给对端,完成后回调函数
bufferevent_write(bev,p,strlen(p)+1);
sleep(1);
}
//写缓冲区回调
void write_cb(struct bufferevent *bev, void *data)
{
cout<<"成功将数据写给客户端"<<endl;
}
//事件回调
void event_cb(struct bufferevent *bev, short events, void *data)
{
if (events & BEV_EVENT_EOF)
{
cout<<"connection closed"<<endl;
}
else if(events & BEV_EVENT_ERROR)
{
cout<<"some other error"<<endl;
}
bufferevent_free(bev);
cout<<"buffevent 资源已经被释放"<<endl;
}
//监听回调函数
void cb_listener(
struct evconnlistener *listener,
evutil_socket_t fd,
struct sockaddr *addr,
int len, void *ptr)
{
cout<<"connect new client"<<endl;
struct event_base*base=(struct event_base*)ptr;
//创建bufferevent事件对象
struct bufferevent *bev;
bev=bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
//给bufferevent缓冲区设置回调
bufferevent_setcb(bev,read_cb,write_cb,event_cb,NULL);
bufferevent_enable(bev, EV_READ);
return ;
}
int main (int argc,const char*argv[])
{
//创建地址结构并初始化
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(9876);
server.sin_addr.s_addr = htonl(INADDR_ANY);
//创建event_base
struct event_base *base;
base=event_base_new();
//创建监听器(创建套接字,绑定,接收收连接请求)
struct evconnlistener *listener;
//evconnlistener_new_bind()函数返回监听器对象
listener=evconnlistener_new_bind(
base,cb_listener,base,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
-1,
(struct sockaddr *)&server,
sizeof(server));
//启动循环监听
event_base_dispatch(base);
//释放监听器
evconnlistener_free(listener);
//释放event_base
event_base_free(base);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
void read_cb(struct bufferevent *bev, void *arg)
{
char buf[1024] = {0};
bufferevent_read(bev, buf, sizeof(buf));
cout<<"fwq say:"<<buf<<endl;
bufferevent_write(bev, buf, strlen(buf)+1);
sleep(1);
}
void write_cb(struct bufferevent *bev, void *arg)
{
cout<<"----------我是客户端的写回调函数"<<endl;
}
void event_cb(struct bufferevent *bev, short events, void *arg)
{
if (events & BEV_EVENT_EOF)
{
cout<<"connection closed"<<endl;
}
else if(events & BEV_EVENT_ERROR)
{
cout<<"some other error"<<endl;
}
else if(events & BEV_EVENT_CONNECTED)
{
cout<<"已经连接服务器..."<<endl;
return;
}
// 释放资源
bufferevent_free(bev);
}
// 客户端与用户交互,从终端读取数据写给服务器
void read_terminal(evutil_socket_t fd, short what, void *arg)
{
// 读数据
char buf[1024] = {0};
int len = read(fd, buf, sizeof(buf));
struct bufferevent* bev = (struct bufferevent*)arg;
// 发送数据
bufferevent_write(bev, buf, len+1);
}
int main(int argc, const char* argv[])
{
struct event_base* base = NULL;
base = event_base_new();
int fd = socket(AF_INET, SOCK_STREAM, 0);
// 通信的fd放到bufferevent中
struct bufferevent* bev = NULL;
bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
// init server info
struct sockaddr_in serv;
memset(&serv, 0, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = htons(9876);
inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);
// 连接服务器
bufferevent_socket_connect(bev, (struct sockaddr*)&serv, sizeof(serv));
// 设置回调
bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
// 设置读回调生效
// bufferevent_enable(bev, EV_READ);
// 创建事件
struct event* ev = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST,
read_terminal, bev);
// 添加事件
event_add(ev, NULL);
event_base_dispatch(base);
event_free(ev);
event_base_free(base);
return 0;
}