高性能io框架库libevnet 简介

 

libevent 库简介

libevent 是一款事件驱动的网络开发包,由于采用c语言开发 ,体积小,跨平台,速度极快,大量开源项目使用了libevent比如谷歌浏览器,和分布式告诉缓存系统memcached,libevnet支持kqueue,select,poll,epoll,iocp(非阻塞的工作模式),事件内部机制完全独立于公开的额事件api,libevnet 支持跨平台,可在linux,windows 等平台上编译,

优点:精简,跨平台,线程安全,专注于网络通信

下载--解压--安装

源码包安装:REANME

./config  检查安装环境 生成makefile

make 编译,生成.o可执行文件

 sudo make install   将必要的资源拷贝到系统指定的目录

进入sample目录,运行demo验证 库安装使用的情况

编译使用库的.c时,需要加-levent选项

库名libevent.so  /usr/lib

特点:基于“事件”异步通信模型--回调

 

libevnet框架

创建 event_base(乐高的底座)

创建事件 event

将事件添加到 base上

循环监听事件满足

释放event_base

(1)创建 event_base(底座)

struct event _base *event_base_new(void);//创建函数;

struct event_base*base=evnet_base_new();

 

(2)创建事件

常规事件 event------>evnet_new();

 

bufferevent----------->bufferevnet_socket_new();

 

 

 

(3)将事件添加到base上

int event_add (struct *ev,const struct timeval *tv);

ev:event_new()函数返回的事件

TV:为null时,不会超时,意思是一直等到事件被触发,回调函数会被调用

       为非0,等待期间检查事件没有被触发,时间到回调函数依然会被调用

 

(4)循环监听事件满足

int event_base_dispatch(struct event_base *base);

event_base_dispatch(base);成功返回0,失败返回-1;

只有event_new 中指定了EV_PERSIST才持续触发,否则只触发一次就跳出循环

通常这样:EV_WRITE|EV_PERSIST  ,  EV_READ|EV_PERSIST

其他循环;

int event_base_loopexit(struct evnet_base *base,const struct timecal*tv);

在指定时间后停止循环

int event_base_loopbreak(struct evnet_base *base);立即停止循环

(5)释放event_base

void event_base_free(struct event_base*base);//释放函数;

event _base_free(base);

 

特征:基于事件的异步通信模型,所见皆事件,等某个条件到达时去执行某个函数(回调机制)-----回调

 

相关函数了解:

查看支持哪些多路io

const char ** evnet_get_supported_methods(void);

查看当前用的多路io

const char *event_base_get_method(const struct event_base *base);

查看fork()后子进程使用的event_base

int event_reinit(struct event_base *base);

成功0  失败-1;

使用该函数后,父进程创建的base在子进程生效。

#include
#include

#include

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}
int mian()
{
    struct event_base *base=event_base_new();
/*    
    const char **buff;

    buff=event_get_supported_methods();
    for(int i=0;i<10;i++)
    {
        printf("buff[i]=%s\n",buff[i]);
    }
*/
    char *buf;
    buf=event_base_get_method(base);
    printf("buf=%s\n",buf);
    return 0;
}

创建事件:struct eevent *event_new(struct evnet_base *base,evutil_socket_t fd,short what,evnet_callback_fn cb,void arg);

第一个参数base:底座

第二个参数:绑定到事件上的文件描述符

第三个参数:对该文件描述符监听什么事件,读,写,执行

第四个参数:指定回调函数

第五个参数:指定回调函数的参数

 

 

常规事件创建/销毁

 

 

 

struct event *event_new(struct evnet_base *base,evutil_socket_t fd,short what,event_callbacj_fn cb,void arg);

第一个参数:event_base_new()的返回值 ,就是乐高的底座
第二个参数:绑定到event 上的文件描述符
第三个参数:对捆绑的文件描述符监听什么事情(读写异常r,w,e)
第四个参数:监听的事件满足条件,执行的回调函数
第五个参数:回调函数的参数
返回值:成功创建的ecent

what EV_READ EV_WORTE EV_PERSIST持续触发 结合event_base_dispatch()函数使用生效
回调函数类型
typedef void (*event_callback_fn)(evutil_socket_t fd,short,void*);

添加事件到base上

int event_add(event_new *ev,const struct timeval *tv);
ev:event_new()函数的返回值
tv:
为NULL 不会超时
为非零,等待时间,检查的时间没有被触发,时间到,函数依然会被调用

销毁事件

int event_del(struct event *ev);
//将事件从base上拿下来
ev:event_new()的返回值

销毁事件
int evnet_free(struct event*ev);
ev:event_new()的返回值

未决和非未决

高性能io框架库libevnet 简介_第1张图片

 

未决:创建的事务对象有资格被处理,但是还没有被处理

非未决:创建的事务对象没有资格被处理

 

默认创建的新事件是非未决状态的,因为事务还没有添加到base上

 

bufferevent

 

高性能io框架库libevnet 简介_第2张图片

高性能io框架库libevnet 简介_第3张图片

bufferevent
#inlcude
原理:bufferevent有两个缓冲区,借助消息队列实现,内部的数据只能读一次,先进先出
读:有数据->读回调函数被调用->使用bufferevent_read()读数据
写:使用bufferevent_write()->向缓冲区写数据->该缓冲区有数据自动写出->写完,回调函数被调用 

带缓冲区的事件创建/销毁

创建

struct bufferevent *ev;
struct bufferevnet *bufferevent_socket_new(struct event_base *base,evutil_socket_t fd,enum bufferevent_options options);

base:    event_base_new()函数的返回值
fd:      跟bufferevent绑定的文件描述符,类比event_new()
options: BEV_OPT_CLOSE_ON_FREE,只用这一个即可

返回:成功创建bufferevent事件对象

销毁

void bufferevent_free(struct bufferevent *ev);
ev//上面函数的返回值;

给读写回调缓冲区设置回调

struct bufferevent *ev;
struct bufferevnet *bufferevent_socket_new(struct event_base *base,evutil_socket_t fd,enum bufferevent_options options);

base:    event_base_new()函数的返回值
fd:      跟bufferevent绑定的文件描述符,类比event_new()
options: BEV_OPT_CLOSE_ON_FREE,只用这一个即可

返回:成功创建bufferevent事件对象




/
/
/

void bufferevnet_setcb(struct bufferevent *bufev,
                      bufferevent_data_cb readcb,
                      bufferevent_data_cb writecb,
                      bufferevnet_event_cb evnetcb,
                      void *cbag);

bufev: bufferevnet_socket_new()函数的返回值
readcb:读缓冲对应的回调,自己封装,在其内部读数据,注意使用bufferevnet_read()读,而不是read()
writecb:不用它,传空即可
eventcb:可以传空
cbarg:回调函数用的参数
readcb对应的回调函数:
typedef void (*bufferevent_data_cb)(struct bufferevent*bev,void ctx);


如:
void read_cb(struct bufferevnet*bev,void arg)
{             
    bufferevent_read();//读数据,类似于read()
}
读数据从bufferevent输入缓冲区中移除数据



bufferevnet_read()函数原型
size_t bufferevent_read(struct bufferevent *bufev,void *data,size_t size);
通常在readcb中,替代read()




bufferevnet_write()函数原型
int bufferevent_write(struct bufferevent *bufev,const void *data,size_t size);

通常在buff erevent_read之后,替代write()

typedef void (*bufferevent_event_cb)(struct bufferevnet *bev,short events,void *ctx);

void event_cb(struct bufferevnet *bev,short events,void ctx)
{
    .....
}
events:BEV_EVENT_CONNECTED

 

 

高性能io框架库libevnet 简介_第4张图片

 

缓冲区的禁用启用

 

高性能io框架库libevnet 简介_第5张图片

 

 

默认:新建的bufferevnet写缓冲是enable的,读缓冲是disable的

void bufferevnt _enable(struct bufferevnt *bufev,short evnets);
启用缓冲区
通常用发来启用bufferevent的read缓冲区

void bufferevent_disable(structevent *bufev,short events);
禁用缓冲区
events:EV_READ,EV_WRITE,EV_READ|EV_WRITE

short bufferevent_get_enable(struct bufferevnet *bufev);
获取缓冲区的近用状态,需要借助&来得到

 

网络通信

客户端:socket();connect();

int bufferevnet_socket_connect(struct bufferevnet *bev,struct sockaddr*address,int addrlen);

bev:bufferevnet事件对象,封装了fd

address和addrlen就是connect()函数的第二第三个参数

 

服务器:socket(),bind(),listen();accept();

//创建监听服务器
struct evconnlistener*listener;
struct evconnlistener*evconnlistener_new_bind(
struct event_base *base,
evconnlistener_cb cb,
void *ptr,
unsigned flags,
int backlog,
const struct sockaddr *sa,
int socklen);

//释放监听服务器
返回值为空
evconnlistener_free(listener);

base:evnet_base

cb:回调函数,一旦被回调,说明在其内部应该与客户端完成读写操作,进行通信

ptr:表示回调函数的参数

flags:表示可以识别的标志

 

LEV_OPT_CLOSE_ON_FREE:释放bufferevent时关闭底层连接端口,这将关闭底层套接字,释放底层bufferevent等

LEV_OPT_REUSEABLE端口复用

backlog:listen()的第二个参数,传 -1,表示使用默认最大值

sa:服务器的ip+port,,服务器自己的地址结构

socklen:sa 的大小,,服务器自己的地址结构大小

返回值:成功创建的监听器
 

typedef void(*evconnlistener_cb)(struct evconnlistener*listener,
evutil_socket_t sock;
struct sockaddr*addr,
int len,
void *ptr
);
listener:evconnlisten_new_bind()的返回值
sock:用于与客户端通信的文件描述符 cfd
addr:客户端的地址结构
len:客户端地址结构的长度
ptr:外部ptr传进来的值

注:该回调函数不是由我们调用的,是框架自动调用,因此只需要直到参数含义

该回调函数完成与客户端的读写操作

里面使用bufferevnet_read() bufferevnet_write()去读写

高性能io框架库libevnet 简介_第6张图片

#include
#include
#include
#include
#include
#include
#include
#include
#include
//读缓冲区
void read_cb(struct bufferevnet *bev,void arg)
{
	char buf[1024]={0};
	bufferevnet_read(bev,buf,sizeof(buf));
	printf("client say:%s\n",buf);

	char *p="我是服务器,已经受到了你写的数据";

	//写数据给客户端
	bufferevnet_write(bev,p,strlen(p)+1);
	sleep(1);

}
//写缓冲区回调
void write_cb(struct bufferevnet *bev,void *arg)
{
	printf("我是服务器,成功写数据给客户端,写缓冲区回调函数被回调\n");
}


//监听回调   这个函数被调用说明客户端已经连接上来了
void cb_listener(struct evconnlistener *listener,
				 evutil_socket_t fd,
				 struct sockaddr *addr,
					 int len,void ptr)
{
	printf("connect new client\n");
	struct event_base*base=(struct event_base*)ptr;

	//添加事件
	struct bufferevnet *bev;
	bev=bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);

	//给Bufferevent缓冲区设置回调
	bufferevnet_setcb(bev,read_cb,write_cb,event_cb,NULL);
	//启用bufferevent的读缓冲区,默认是disable的
	bufferevent_enable (bev,EV_READ);
}
int main(int argc,const char*argv[])
{
	//初始化服务器
	struct socket_in serv;

	memset(&serv,0,sizeof(serv));
	serv.sin_family=AF_INET;//指定服务器的地址结构
	serv.sin_port=htons(9876);//指定ipv4端口号
	serv.sin_addr.s_addr=htonl(INDOOR_ANY);//指定ipv4IP地址


	//创建event_base框架
	struct event_base *base;
	base=event_nase_new();

	/*
	struct bufferevent *bev;
	bev=bufferevent_socket_new();
	这个时间要在有链接之后才能读写数据,应该先监听有描述符了之后在进行读写
	*/
	struct evconnlistener*listener;
	listener=evconnlistener_new_bind(base,cb_listener,base,LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
		36,(struct sockaddr*)&serv,sizeof(serv));

	event_base_diapatch(base);
	evconnlistener_free(listener );
	event_base_free(base);
	return 0;

}

 

高性能io框架库libevnet 简介_第7张图片

高性能io框架库libevnet 简介_第8张图片

高性能io框架库libevnet 简介_第9张图片

 

 

高性能io框架库libevnet 简介_第10张图片

 

高性能io框架库libevnet 简介_第11张图片

高性能io框架库libevnet 简介_第12张图片

高性能io框架库libevnet 简介_第13张图片

 

 

你可能感兴趣的:(Linux)