网络编程-libevent

libevent

网络的事件库
跨平台,支持多种多路io复用
核心:以事件驱动(触发)回调

1、安装libevent

  • 先下载linux下的安装包
  • 解压:tar -zxvf libevent-2.0.22-stable.tar.gz -C ./install(解压到install目录下)
    执行configure(该文件存在于解压好的文件中),检测环境生成makefile
    ./configure
  • 编译
    sudo make
  • 安装
    sudo make install
    库路径:/usr/local/lib
    头文件目录:/usr/local/include

使用gcc进行编译时需要加上库名 -levent

2、libevent的使用
创建event_base根节点

struct event_base *event_base_new(void);
返回值就是event_base根节点地址

释放根节点

void event_base_free(struct event_base *);

循环监听

int event_base_dispatch(struct event_base *base);
相当于while(1){epoll_wait}循环监听

退出循环监听

int event_base_loopexit(struct event_base *base, const struct timeval *tv);//等待固定时间后退出
int event_base_loopbreak(struct event_base *base);//立即退出

3、libevent事件触发流程
网络编程-libevent_第1张图片4、libevent相关API
初始化上树节点

struct event *event_new(struct event_base *base, evutil_socket_t fd, short events, event_callback_fn cb, void *arg);
参数:
	base:event_base根节点
	fd:上树的文件描述符
	events:监听的事件
			#define  EV_TIMEOUT   0x01 //超时事件
			#define  EV_READ         0x02 //读事件
			#define  EV_WRITE       0x04  //写事件
			#define  EV_SIGNAL     0x08  //信号事件
			#define  EV_PERSIST   0x10  //周期性触发
			#define  EV_ET          
	cb:回调函数
			typedef void(*event_callback_fn)(evutil_socket_t fd, short events, void *arg);
	arg:传给回调函数的参数
返回值:初始化好的节点的地址

节点上树

int event_add(struct event *ev, const struct timeval *timeout);
参数:
	ev:上树节点的地址
	timeout:NULL永久监听   固定时间限时等待

释放节点

void event_free(struct event *ev);

5、使用libevent编写tcp服务器流程
创建套接字
绑定
监听
创建event_base根节点
初始化上树节点 lfd
上树
循环监听
收尾

示例:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//回调函数
void cfdcb(int cfd, short event, void *arg)
{
	char buf[1024] = "";
	int n = read(cfd, buf, sizeof(buf));
	if(n <= 0)
	{
		perror("err or close\n");
		//event_del(); //下树
	}
	else
	{
		printf("%s\n",buf);
		write(cfd, buf, n);
	}
}
void lfdcb(int lfd,short event, void *arg)
{
	struct event_base *base = (struct event_base *)arg;
	//提取新的cfd
	int cfd = accept(lfd,NULL,NULL);
	//将cfd上树
	struct event *ev = event_new(base,cfd,EV_READ | EV_PERSIST,cfdcb,NULL);
	event_add(ev,NULL);
}

int main(int argc, char *argv[])
{
	//1、创建套接字
	int lfd = socket(AF_INET,SOCK_STREAM,0);
	//2、绑定
	struct sockaddr_in myaddr;
	myaddr.sin_family = AF_INET;
	myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	myaddr.sin_port = htons(atoi(argv[1]));
	bind(lfd,(struct sockaddr *)&myaddr,sizeof(myaddr));
	//3、监听
	listen(lfd, 128);
	//4、创建event_base根节点
	struct event_base * base = event_base_new();
	//5、初始化lfd上树节点
	struct event *ev = event_new(base,lfd,EV_READ | EV_PERSIST,lfdcb,base);
	//6、上树
	event_add(ev,NULL);
	//7、循环监听
	event_base_dispatch(base);//阻塞
	//8、收尾
	close(lfd);
	event_base_free(base);
	return 0;
}

6、bufferevent事件
普通的event事件 一个文件描述符 事件(底层缓冲区的读事件或者写事件)触发回调
高级的event事件 bufferevent事件
核心:一个文件描述符 两个缓冲区 三个回调事件
网络编程-libevent_第2张图片7、bufferevent事件的监听流程
网络编程-libevent_第3张图片
8、bufferevent事件的API
创建新的节点

struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, int options);
参数:
	base:event_base根节点
	fd:要初始化上树的文件描述符
	options:
	    BEV_OPT_CLOSE_ON_FREE   -- 释放bufferevent自动关闭底层接口   
         BEV_OPT_THREADSAFE      -- 使bufferevent能够在多线程下是安全的
返回值:
	新建节点的地址

设置节点的回调

void bufferevent_setcb(struct bufferevent *bufev,bufferevent_data_cb readcb, bufferevent_data_cb writecb,bufferevent_event_cb eventcb, void *cbarg);
参数:
	bufev:新建的节点的地址
	readcb:读回调
	writecb:写回调
	eventcb:异常回调
	cbarg:传给回调函数的参数
		typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx);// 读写回调
    	typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short what, void *ctx);//事件回调
    		what:
 				BEV_EVENT_EOF, 对方关闭连接
				BEV_EVENT_ERROR,出错
				BEV_EVENT_TIMEOUT,超时
				BEV_EVENT_CONNECTED 建立连接成功

让事件使能

int bufferevent_enable(struct bufferevent *bufev, short event);//EV_READ EV_WRITE
int bufferevent_disable(struct bufferevent *bufev, short event);//EV_READ  EV_WRITE

发送数据

int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size);
将data的数据写到bufferevent的写缓冲区

接收数据

size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
将bufferevent的读缓冲区数据读到data中,同时将读到的数据从bufferevent的读缓冲区清除

9、连接侦听器
作用:创建套接字,绑定,监听,提取

struct evconnlistener *evconnlistener_new_bind(struct event_base *base,evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,const struct sockaddr *sa, int socklen);
参数:
	base:base根节点
	cb:提取cfd后调用的回调
	ptr:传给回调的参数
	flags:
		LEV_OPT_LEAVE_SOCKETS_BLOCKING   文件描述符为阻塞的
         LEV_OPT_CLOSE_ON_FREE            关闭时自动释放
         LEV_OPT_REUSEABLE                端口复用
         LEV_OPT_THREADSAFE               分配锁,线程安全
     backlog:-1 表示自动填充
     sa:绑定的地址信息
     socklen:sa的大小
返回值:
	连接侦听器的地址

回调函数

typedef void (*evconnlistener_cb)(struct evconnlistener *evl, evutil_socket_t fd, struct sockaddr *cliaddr, int socklen, void *ptr);
参数:
	evl:连接侦听器的地址
	fd:cfd
	cliaddr:客户端的地址信息
	ptr:evconnlistener_new_bind传过来的参数

10、创建套接字,连接服务器

struct bufferevent *bufferevent_socket_new(struct event_base *base,-1, int options);
int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *serv, int socklen);

bev:新建的节点
serv:服务器的地址信息
socklen:serv长度

你可能感兴趣的:(网络,linux,服务器)