1、Libevent简介
livevent是一个轻量级的开源的高性能的事件触发的网络库,适用于windows、linux、bsd等多种平台,内部使用select、epoll、kqueue等系统调用管理事件机制。Libevent是用于编写高速可移植非阻塞IO应用的库。
2、Libevent安装
ubuntu@VM-0-7-ubuntu:~/Project$ wget
https://github.com/libevent/libevent/releases/download/release-2.1.10-stable/libevent-2.1.10-stable.tar.gz
ubuntu@VM-0-7-ubuntu:~/Project$ tar -xzvf libevent-2.1.10-stable.tar.gz
ubuntu@VM-0-7-ubuntu:~/Project$ cd libevent-2.1.10-stable/
配置编译选项,如需交叉编译可在这一步指定交叉编译器以及安装路径–prefix指定编译路径 --host接编译后运行的机器 CC和CXX选项接交叉编译器
ubuntu@VM-0-7-ubuntu:~/Project/libevent-2.1.10-stable$ ./configure
ubuntu@VM-0-7-ubuntu:~/Project/libevent-2.1.10-stable$ make
ubuntu@VM-0-7-ubuntu:~/Project/libevent-2.1.10-stable$ sudo make
install
3、libevent使用
3.1、创建event_base事件集合以及event事件函数
使用libevent函数之前需要分配一个或者多个event_base结构体。每个event_base结构体持有一个事件集合,可以检测以确定哪个事件是激活的。如果需要用多个线程检测IO,则需要为每个线程使用一个event_base。event_base_new()函数分配并且返回一个新的具有默认设置的event_base。
struct event_base *event_base_new(void);
接着就需要在base事件集合下创建event事件,event_new()试图分配和构造一个用于base的新的事件,设置事件标志读事件、写事件、边沿触发、信号还有持久化以及事件发生的回调函数。
struct event *event_new(struct event_base *base, evutil_socket_t fd,
short what, event_callback_fn cb, void *arg) ;
下面是可监听的事件标志:
#define EV_TIMEOUT 0x01
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
#define EV_PERSIST 0x10
#define EV_ET 0x20
接着调用event_add()将添加事件,第一个参数为添加的事件,第二个参数可设置超时时间,若传NULL空指针则不超时。
int event_add(struct event *ev, const struct
timeval *tv)
启用事件循环,libevent循环处理事件,event_base_dispatch等同于没有设置标志的event_base_loop。所以,event_base_dispatch()将一直运行,直到被注册的事件全部被移除,或者调用了event_base_loopbreak()或者event_base_loopexit()为止。
int event_base_loop(struct event_base *base, int flags);
int event_base_dispatch(struct event_base *base);
3.2、bufferevent函数
多时候,除了响应事件之外,应用还希望做一定的数据缓冲。就用到bufferevent,基于套接字的bufferevent是最简单的,它使用libevent的底层事件机制来检测底层网络套接字是否已经就绪,可以进行读写操作,并且使用底层网络调用(如read、write)来发送和接收数据。
使用bufferevent_socket_new()创建基于套接字的bufferevent,将需要监听的文件描述符fd添加的到事件集合base中去,options为掩码通常为BEV_OPT_CLOSE_ON_FREE,表示释放bufferevent时关闭底层传输端口。这将关闭底层套接字,释放底层bufferevent等。
struct bufferevent *bufferevent_socket_new(struct event_base *base,
evutil_socket_t fd,
enum bufferevent_options options);
接着调用bufferevent_setcb()函数设置回调函数。readcb、writecb和eventcb函数将分别在已经读取足够的数据、已经写入足够的数据,或者发生错误时被调用,最后void *cbarg是传入回调函数的参数。
void bufferevent_setcb(struct bufferevent *bufev,
bufferevent_data_cb readcb, bufferevent_data_cb writecb,
bufferevent_event_cb eventcb, void *cbarg);
最后启用bufferevent上的EV_READ、EV_WRITE或者EV_READ | EV_WRITE事件,与之前的ev_add添加事件类似。
void bufferevent_enable(struct bufferevent *bufev, short events);
3.3、Libevent服务器程序
/*********************************************************************************
* Copyright: (C) 2020 WuYuJun<540726307@qq.com>
* All rights reserved.
*
* Filename: libevent_demo.c
* Description: This file
*
* Version: 1.0.0(05/31/2020)
* Author: WuYuJun <540726307@qq.com>
* ChangeLog: 1, Release initial version on "05/31/2020 03:00:52 PM"
*
********************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <assert.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include<event.h>
#include<event2/bufferevent.h>
#include<event2/buffer.h>
#include<event2/util.h>
int tcp_server_init(int port, int back_log) ;
void accept_cb(int fd, short events, void* arg) ;
void socket_read_cb(struct bufferevent* bev, void* arg) ;
void event_cb(struct bufferevent *bev, short event, void *arg) ;
void to_upper(const char<