当前位置:   article > 正文

linux入门到精通-第二十章-bufferevent(开源高性能事件通知库)_bufferevent 高性能tcp

bufferevent 高性能tcp

参考

视频教程
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 在执行回调的时候不进行锁定。
返回值:
	新建节点的地址
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

设置事件节点回调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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

使事件势能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);

  • 1
  • 2
  • 3
  • 4
  • 5

发送数据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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

接收数据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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意,对于 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,完成监听
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/974798
推荐阅读
相关标签
  

闽ICP备14008679号