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


    参考

    视频教程
    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,完成监听
    };
    
  • 相关阅读:
    vue3中实现放大镜效果,使用ref获取节点元素
    吴恩达《微调大型语言模型》笔记
    pod(一):Kubernetes(k8s)创建pod的两种方式
    Cocos 进度条物体跟随效果
    Scala入门教程
    基于JAVA图书管理系统计算机毕业设计源码+数据库+lw文档+系统+部署
    企业帮助中心如何在线搭建,还能多场景使用呢?
    极致CMS翻译插件自动批量多语种翻译
    postman教程-14-生成随机数
    MQ 之 RocketMQ整合进SpringBoot项目
  • 原文地址:https://blog.csdn.net/Blueeyedboy521/article/details/131239900