libevent库
开源。精简。跨平台(Windows、Linux、Maxos、unix)。专注于网络通信。
源码包安装:
./configure 检查安装环境 生成makefile
生成.o和可执行文件
将必要的资源cp至系统指定目录。
进入sample目录,运行demo验证库安装使用情况。
编译使用库的.c时,需要加-levent选项。
库名libevent.so--> /usr/local/lib 查看得到。
特性:
基于“事件”异步通信模型。---回调。
libevent框架:
1.
创
建event_base (乐高底座)
struct event_base *event_base_new(void);
struct event_base *event *base=event_base_new();
2.
创建 事
件event
常规事件 event -->event_new();
bufferevent -->bufferevnet_socket_new();
3. 将事件 添加到base上
int event_add(struct event *ev,const struct timeval *tv);
4. 循环监听事件满足
int event_base_dispatch(struct event_base *base);
event_base_dispatch(base);
5. 释放 event_base
event_base_free(base);
创建事件:
struct event *ev;
struct event *evennt_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
添加事件到event_base
int event_add(struct event *ev,const struct timeval *tv);
ev: event_new()的返回值。
tv:NULL
从event_base上摘下事件 【了解】
int event_del(struct event *ev);
ev:event_new()的返回值。
销毁事件:
int event_free(struct event *ev);
ev:event_new()的返回值。
未决和非未决:
非未决:没有资格被处理
未决:有资格被处理,但尚未被处理
event_new--->event---->非未决--->event_add--->未决--->dispatch()&&监听事件被触发-->激活态
——>执行回调函数--->处理态--->非未决 event_add && EV_PERSIST---->未决--->event_del--->非未决
带缓冲区的事件 bufferevent
#include<event2/buffereevent.h>
创建、销毁bufferevent
struct bufferent *ev;
struct bufferevent *bufferevent_socket_new(struct event_base *base,evutil_socket_t fd,enum bufferevent_options options);
base: event_base
fd: 封装到bufferevent内的fd
options: BEV_OPT_CLOSE_ON_FREE
返回:成功创建的bufferevent事件对象。
void bufferevent_socket_free(struct bufferevent *ev);
给bufferevent设置回调:
对比event:event_new(fd,callback); event_add() --- 挂到event_base上。
bufferevent_socket_new(fd) bufferevent_setcb(callback)
void bufferevent_setcb(struct bufferevent*bufev, bufferevent_data_cb reacb, bufferevent_data_cb writecb, bufferevent_data_cb eventcb , void *cbarg );
bufev:bufferevent_socket_new()返回值
readcb:设置bufferevent 度缓冲,对应回调 read_cb{ bufferevent_read() 读数据 }
writecb:设置bufferevent 写缓冲,对应回调write_cb{ } ---给调用者,发送写成功通知。 可以NULL
eventcb:设置事件回调。 也可以传NULL
typedef void(*bufferevent_data_cb)(struct bufferevent *bev,void*ctx);
void event_cb(struct bufferevent *bev, short events, void *cbarg)
{
。。。。。
}
cbarg:上述回调函数使用的参数。
read 回调函数类型:
typedef void(*bufferevent_data_cb)(struct bufferevent *bev,void*ctx);
void read_cb(struct bufferevent *bev,void *cbarg)
{
.....
bufferevent_read(); ---read()
}
bufferevent_read()函数的原型:
size_t bufferevent_read(struct bufferevent *bev, void *buf, size_t bufsize);
write 回调函数类型:
int bufferevent_write(struct bufferevent *bufev, const void*data,size_t size);
启动、关闭bufferevent的 缓冲区:
void bufferevent_enable(struct bufferevent *bufev, short events); 启动
events: EV_READ、EV_WRITE、EV_READ|EV_WRITE
默认、write 缓冲区 enable、read缓冲区是disable
bufferent_enable(event,EV_READ); --开启读缓冲
创建监听服务器:
socket();bind();listen();accept();
struct evconnlistener *listner
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:event_base
cb:回调函数。 一旦被回调,说明在其内部应该与客户端完成,数据读写操作,进行通信。
ptr:回调函数的参数
flags:LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE
backlog:listen() 2参。 -1表最大值
sa:服务器自己的地址结构体
socklen:服务器自己的地址结构体大小。
返回值:成功创建的监听器。
连接客户端:
socket(); connect();
int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen);
bev:bufferevent 事件对象(封装了fd)
address、len:等同于connect()参2/3
服务器端libevent创建TCP连接:
- 1.创建event_base
- 2.创建bufferevent事件对象。bufferevent_socket_new();
- 3.使用bufferevent_setcb()函数给bufferevent的read、write、event设置回调函数。
- 4.当监听的事件满足时,read_cb会被调用,在其内部bufferevent_read(); 读
- 5.使用evconnlistener_new_bind创建监听服务器,设置其回调函数,当有客户端成功连接时,这个回调函数会被调用。
- 6.封装listner_cb()在函数内部。完成与客户端通信。
- 7.设置读缓冲、写缓冲的 使能状态 enable、disable
- 8.启动循环event_base_dispath();
- 9.释放连接
客户端libevent创建TCP连接:
- 1.创建event_base
- 2.使用bufferevent_socket_new()创建一个用跟踪服务器通信的bufferevnet事件对象
- 3.使用bufferevent_socket_connect()连接 服务器
- 4.使用bufferevent_setcb()给bufferevnet对象的read、write、event设置回调
- 5.设置bufferenet对象的读写缓冲区enable/disable
- 7.启动循环event_base_dispath();
- 8.释放连接
web——HTTP请求协议:
- 1.getline()获取http协议的第一行。
- 2.从首行中拆分 GET、文件名、协议版本。获取用户请求的文件名。
- 3.判断文件是否存在。stat()
- 4.判断是文件还是目录。
- 5.是文件--open--read --写会给浏览器
- 6.先写http应答协议头:http/1.1 200 ok
- 7.写文件数据。