libevent库

优点:
开源。精简。跨平台(Windows,Linux,macOS,Unix)。专注于网络。
安装: 参考readme
./configure
make
sudo make install
进入sample目录。运行监测
编译使用库的.c需要加 -levent选项
特性:
基于“事件”异步通信模型。 — 回调。

libevent库框架

创建event_base

struct event_base *event_base_new(void);
struct event_base *base = event_base_new();

创建事件event
常规事件 event _new();
bufferevent bufferevent_socket_new();

将事件 添加到base上

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

循环监听时间满足

int event_base_dispatch(struct event_base *base);

释放event_base

void event_base_free(struct event_base *base);

在这里插入图片描述
创建事件

struct event *ev;
struct event *event_new(struct event_base *base,evutil_socket_t fd,short what,event_callback_fn cb,void *arg);1  event_base_new()返回值
fd  绑定到event上的文件描述符
what 对应的事件(读,写,异常)
EV_READ|EV_WRITE 一次读|写事件
EV_PERSIST持续触发(必须结构event_base_dispatch函数使用,生效)
cb  一旦事件满足监听条件,回调的函数
typedef void(*event_callback_fn)(evutil_socket_t fd,short,void *);
arg 回调函数的参数
返回值:成功创建的event

添加事件到event_base

int event_add(struct event *ev,const struct timeval *tv);1:event_new的返回值。

参2:在这里插入图片描述
将事件从event_base上摘下(了解)

int event_del(struct event *ev);

释放事件

int event_free(struct event *ev);
参数:event_new()的返回值

使用fifo的读写

读端

mkfifo("myfifo",0664);
int fd = open("myfifo",O_RDONLY|O_NONBLOCK);

struct event_base *base = event_base_new();
//创建event_base
struct event *ev = event_new(base,fd,EV_READ|EV_PERSIST,read_cb,NULL);
//创建事件
event_add(ev,NULL);
//事件循环
event_base_dispatch(base);
//事件循环
event_free(ev);
event_base_free(base);
close(fd);
//释放资源

void read_cb(evutil_socket_t fd,short what,void *arg)
{
	char buf[1024] = {0};
	int len = read(fd,buf,sizeof(buf));//将文件读到缓冲区
	.....
}

写端

int fd = open("myfifo",O_WRONLY|O_NONBLOCK);

struct event_base *base = event_base_new();
//创建event_base
struct event *ev = event_new(base,fd,EV_WRITE|EV_PERSIST,write_cb,NULL);
//创建事件
event_add(ev,NULL);
//事件循环
event_base_dispatch(base);
//事件循环
event_free(ev);
event_base_free(base);
close(fd);
//释放资源

void write_cb(evutil_socket_t fd,short what,void *arg)
{
	char *buf;
	cin >> buf;
	int len = strlen(buf);
	write(fd,buf,len);//将文件读到缓冲区
	.....
}

事件的未决和非未决

在这里插入图片描述
未决:有资格被处理,但还没被处理
非未决:没有资格被处理

bufferevent

主要用于网络通信

在这里插入图片描述
在这里插入图片描述
创建bufferevent

struct bufferevent *bufferevent_socket_new(struct event_base *base,evutil_socket_t fd,enum bufferevent_options options);
base:event_base
fd:封装到bufferevent内的文件描述符

在这里插入图片描述在这里插入图片描述
返回值:成功创建的bufferevent事件对象。
销毁事件

void bufferevent_free(struct bufferevent *bev);

给读写缓冲区设置回调
相当于
bufferevent_socket_new(fd)和bufferevent_setcb(callback)一起完成了
event_new(…);的工作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

禁用启用缓冲区

在这里插入图片描述
客户端

int buffer_event_connect(struct buffer_event *bev,struct sockaddr *address,int addrlen);

服务器

struct evconnlistener *evconnlister_new_bind(
	struct event_base *base,
	evconnlistener_cb cb,
	void *ptr,
	unsighed flags,int backlog,
	const struct sockaddr *sa,int socklen);
base:event_base
cb:回调函数。一旦被回调说明在其内部应该与客户端完成数据读写操作。
ptr:回调函数的参数
flags:LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE
backlog:listen()2参
sa:服务器自己地址结构体
socklen:sa结构体大小
返回值:成功创建的监听器

在这里插入图片描述

1.创建event_base
2.创建服务器连接监听器 evconnlistener_new_bind(),设置evconnlistener_new_bind()函数中回调函数的操作,当有客户端连接成功,这个回调函数会被调用。
3.封装lister_cb()在函数内部
4.创建bufferevent事件对象
5.使用bufferevent_setcb()设置回调函数
6.设置bufferevent的读写缓冲区enable/disable
7.启动循环event_base_dispath();
8.释放连接

释放监听服务器
void evconnlistener_free(struct evconnlistener *lev);

服务器

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>

#define SERV_PORT 9527

//读回调
void read_cb(struct  bufferevent *bev,void *arg)
{
	//需要一个buf
	char buf[1024] = {0};
	bufferevent_read(bev,buf,sizeof(buf));
	printf("recv buf : %s\n",buf);
	//发送数据,向缓冲区写数据
	char *pt = "已收到发送的数据";
	bufferevent_write(bev,pt,strlen(pt) + 1);
	printf("send...\n");
}

void write_cb(struct bufferevent *bev,void *arg)
{
	printf("已发送...");//没什么用
}

void event_cb(struct bufferevent *bev,short events,void *arg)
{
	if(events & BEV_EVENT_EOF)
		printf	("closed...\n");
	//释放bufferevent资源
	bufferevent_free(bev);//这个位置最合适
}

//连接完成之后,对应的操作
void listen_cb(struct evconnlistener *listener,
								evutil_socket_t fd,
								struct sockaddr *addr,
								int len,void *ptr)
{
	//得到传进来的base
	struct event_base*base = (struct event_base*)ptr;
	//接受和发送数据
	//将fd封装为bufferevent
	struct bufferevent *bev = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
	//给读写缓冲区设置回调函数
	bufferevent_setcb(bev,read_cb,write_cb,event_cb,NULL);
	//设置度缓冲区
	bufferevent_enable(bev,EV_READ);
}

int main()
{
	//创建事件处理框架
	struct event_base* base = event_base_new();

	struct sockaddr_in serv;
	serv.sin_family = AF_INET;
	serv.sin_port = htons(SERV_PORT);
	serv.sin_addr.s_addr = htonl(INADDR_ANY);

	//创建监听的套接字
	//绑定
	//监听
	//等待并接受连接
	struct evconnlistener* listen = NULL;
	//有新连接listen_cb被调用
	listen = evconnlistener_new_bind(base,listen_cb,base,
					LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
					-1,(struct sockaddr*)&serv,sizeof(serv));
	
	//开始事件循环
	event_base_dispatch(base);

	evconnlistener_free(listen);
	event_base_free(base);

	return 0;
}

客户端

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>
#include <arpa/inet.h>

#define SERV_PORT 9527

void read_cb(struct bufferevent *bev,void *arg)
{
    char buf[1024] = {0};
    bufferevent_read(bev,buf,sizeof(buf));
    printf("recv...\nbuf:%s",buf);
}
void write_cb(struct bufferevent *bev,void *arg)
{
    printf("发送成功...\n");
}
void event_cb(struct bufferevent *bev,short events,void *arg)
{
    if(events & BEV_EVENT_CONNECTED){
        printf("connected...\n");
        return;
    }
    bufferevent_free(bev);
}
void read_terminal(int fd,short what,void *arg)
{
    //读终端中的数据
    char buf[1024] = {0};
    int len = read(fd,buf,sizeof(buf));
    //将数据发给server
    struct bufferevent *bev = (struct buffevent *)arg;
    bufferevent_write(bev,buf,strlen(buf)+1);
}

int main()
{
    //创建一个事件处理框架
    struct event_base *base = event_base_new();

    struct sockaddr_in serv;
    inet_pton(AF_INET,"192.168.56.128",&serv.sin_addr.s_addr);
    serv.sin_family = AF_INET;
    serv.sin_port = htons(SERV_PORT);
    //连接服务器
    int fd = socket(AF_INET,SOCK_STREAM,0);
    //创建事件
    struct bufferevent *bev = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
   bufferevent_socket_connect(bev,(struct sockaddr *)&serv,sizeof(serv));
   //设置回调
   bufferevent_setcb(bev,read_cb,write_cb,event_cb,NULL);
    //接受键盘输入
    struct event *ev = event_new(base,STDIN_FILENO,EV_READ | EV_PERSIST,read_terminal,bev);
    event_add(ev,NULL);
    //启动事件
    event_base_dispatch(base);
    //释放资源
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值