目录
- 参考
 - bufferevent简单介绍
 - 工作流程
 - 事件
 - Api
 - 新建事件节点 bufferevent_socket_new
 - 设置事件节点回调bufferevent_setcb
 - 使事件势能bufferevent_enable
 - 发送数据bufferevent_write
 - 接收数据bufferevent_read
 
- evconnlistener的简介
 
参考
视频教程
 libevent的基本使用
 libevent–bufferevent的使用与实现
bufferevent简单介绍
一般通过libevent进行网络编程,都是将一个socket的fd与一个event进行绑定,并自行维护一个buffer用于存储从socket上接收的数据,同时可能也用于待发送数据的缓存。然后通过可读可写事件从socket上收取数据写入缓存并进行相应处理,或者将缓存中的数据通过socket发送。
libevent为这种带缓存的IO模式提供了一种通用的机制,那就是bufferevent。一个bufferevent包含了一个底层传输的fd(通常为socket),一个输入buffer和一个输出buffer,并且bufferevent已经帮我们完成了从socket上接收数据写入输入buffer,同时从输出buffer中取出数据通过socket发送,当输入输出缓存中的数据达到一定量时调用我们设置的回调函数。这样使得我们可以更加关注数据的处理。
event_base既可以监听event事件,也可以监听bufferevent事件
event:普通事件,文件描述符,事件(底层缓冲区的读事件或者写事件)触发 回调
 bufferevent:高级event事件,bufferevent事件
工作流程

事件
- BEV_EVENT_READING
在读操作的时候,触发了一个事件。参考其他标识用来查看是哪个事件。 - BEV_EVENT_WRITING
在写的时候触发了事件,参考其他标识查看是哪个事件。 - BEV_EVENT_ERROR
在bufferevent操作时触发了错误。调用EVUTIL_SOCKET_ERROR()获取更多信息。 - BEV_EVENT_TIMEOUT
超时 - BEV_EVENT_EOF
触发了end-of-file标识 - BEV_EVENT_CONNECTED
完成了连接请求。 
Api
新建事件节点 bufferevent_socket_new
struct bufferevent *bufferevent_socket_new(
struct event_base *base,
evutil_socket_t fd,
enum bufferevent_options options);
参数:
	base:根节点
	fd:要初始化上树的文件描述符
	enum bufferevent_options options:
		BEV_OPT_CLOSE_ON_FREE :释放 bufferevent 时关闭底层传输端口。这将关闭底层套接字,释放底层 bufferevent 等。
		BEV_OPT_THREADSAFE :自动为 bufferevent 分配锁,这样就可以安全地在多个线程中使用 bufferevent。
		BEV_OPT_DEFER_CALLBACKS :设置这个标志时, bufferevent 延迟所有回调,如上所述。
		BEV_OPT_UNLOCK_CALLBACKS :默认情况下,如果设置 bufferevent 为线程安全 的,则 bufferevent 会在调用用户提供的回调时进行锁定。设置这个选项会让 libevent 在执行回调的时候不进行锁定。
返回值:
	新建节点的地址
 
设置事件节点回调bufferevent_setcb
// 读写回调函数
typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx);
// 事件回调函数
typedef void (*bufferevent_event_cb)(struct bufferevent *bev,short events, void *ctx);
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:传给回调函数的参数
	
void bufferevent_getcb(struct bufferevent *bufev,
bufferevent_data_cb *readcb_ptr,
bufferevent_data_cb *writecb_ptr,
bufferevent_event_cb *eventcb_ptr,
void **cbarg_ptr);
 
使事件势能bufferevent_enable
void bufferevent_enable(struct bufferevent *bufev, short events);
void bufferevent_disable(struct bufferevent *bufev, short events);
short bufferevent_get_enabled(struct bufferevent *bufev);
 
发送数据bufferevent_write
// 向bufferevent的输出缓冲区添加数据
int bufferevent_write(struct bufferevent *bufev,
const void *data, size_t size);
int bufferevent_write_buffer(struct bufferevent *bufev,
struct evbuffer *buf);
功能:这些函数向 bufferevent 的输出缓冲区添加数据。 bufferevent_write()将内存中从 data 处开 始的 size 字节数据添加到输出缓冲区的末尾 。bufferevent_write_buffer()移除 buf 的所有内 容,将其放置到输出缓冲区的末尾。成功时这些函数都返回 0,发生错误时则返回-1。
 
接收数据bufferevent_read
从bufferevent的输入缓冲区移除数据
size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
int bufferevent_read_buffer(struct bufferevent *bufev,
struct evbuffer *buf);
这些函数从 bufferevent 的输入缓冲区移除数据。bufferevent_read()至多从输入缓冲区移除 size 字节的数据,将其存储到内存中 data 处。函数返回实际移除的字节数。 bufferevent_read_buffer()函数抽空输入缓冲区的所有内容,将其放置到 buf 中,成功时返 回0,失败时返回 -1。
 
注意,对于 bufferevent_read(),data 处的内存块必须有足够的空间容纳 size 字节数据。
evconnlistener的简介
参考:Libevent之evconnlistener详解
 用户仅仅需要通过evconnlistener_new_bind传递回调函数,在aceept成功后,在回调函数里面处理已连接的套接字即可。省去了用户需要处理的一些列麻烦问题。
 evconnlistener其实是对even_base和event的封装而已。
创建套接字 绑定 监听 提取
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:绑定地址信息
返回:
	连接侦听器的地址
//一系列的工作函数,因为listener可以用于不同的协议。
struct evconnlistener_ops {
	int (*enable)(struct evconnlistener *);
	int (*disable)(struct evconnlistener *);
	void (*destroy)(struct evconnlistener *);
	void (*shutdown)(struct evconnlistener *);
	evutil_socket_t (*getfd)(struct evconnlistener *);
	struct event_base *(*getbase)(struct evconnlistener *);
};
//一层一层封装,加上隔离
struct evconnlistener {
	const struct evconnlistener_ops *ops;	//操作函数
	void *lock;								//锁变量,用于线程安全
	evconnlistener_cb cb;					//用户的回调函数
	evconnlistener_errorcb errorcb;			//发生错误时的回调函数
	void *user_data;               			//回调函数的参数,当回调函数执行时候,通过形参传入回调函数内部
	unsigned flags;                			//属性标志 ,例如socket套接字属性,可以是阻塞,非阻塞,reuse等。
	short refcnt;                  			//引用计数
	unsigned enabled : 1;					//位域为1.即只需一个比特位来存储这个成员 
};
struct evconnlistener_event {
	struct evconnlistener base;
	struct event listener;     //内部event,插入到event_base,完成监听
};
                


















