libevent(15)bufferevent filter的过滤器及例子

news2024/9/21 1:35:52

一、bufferevent filter简单说明

filter之类的东西,相信有php框架或java springboot经验的程序员应该很熟悉,就是加载在输入流之前或输出流之后的一个处理器,用来从业务处分离开来做一些额外的事情。

(1)读取(接收)的数据先进入过滤器中,在过滤器处理完成后再传递给用户进行读取,即 过滤在读取之前 ,例如压缩数据要先在 filter 中解压,然后在 underlying 读取解压后的原始;
(2)写入(发送)的数据由用户发起,再传给过滤器,过滤器处理完后再发送出去,即 过滤在写入之后 ,例如在 underlying 中发送的原始数据,会在 filter 中进行压缩后再发送。

二、bufferevent API

1、bufferevent_filter_new

struct bufferevent *
bufferevent_filter_new(struct bufferevent *underlying,
                       bufferevent_filter_cb input_filter,
                       bufferevent_filter_cb output_filter,
                       int options,
                       void (*free_context)(void *),
                       void *ctx);

回调函数 bufferevent_filter_cb:

/**
 * @brief: 回调函数,用于实现 bufferevent 的过滤器
 *
 * @param src: 源事件缓存
 * @param dst: 目的事件缓存
 * @param dst_limit: 写入 dst 的字节上限,-1表示无限制
 * @param mode: 数据刷新模式
 * @param ctx: 用户传递的参数
 *
 * @return: 返回过滤器的处理结果,详见后面说明
 */
typedef enum bufferevent_filter_result (*bufferevent_filter_cb)(
    struct evbuffer *src, struct evbuffer *dst, 
    ev_ssize_t dst_limit, enum bufferevent_flush_mode mode, void *ctx);

// filter 回调函数返回值
enum bufferevent_filter_result {
	// 正常
	BEV_OK = 0,
	// 还需要更多的数据才能输出
	BEV_NEED_MORE = 1,
	// filter 发生错误,无法进一步处理数据
	BEV_ERROR = 2
};

// filter 数据刷新模式
enum bufferevent_flush_mode {
	// 正常处理数据
	BEV_NORMAL = 0,
	// 检查发送的所有数据
	BEV_FLUSH = 1,
	// 读完或写完数据后,会有 EOF 标志
	BEV_FINISHED = 2
};

2、evbuffer 结构体

这个结构体就是在 filter bufferevent 和 underlying bufferevent 之间传递数据用的。

(1)evbuffer 只是一个数据缓冲区,使用链表实现,不带任何 I/O 操作。
(2)bufferevent 是一个事件缓冲 I/O,内部实现了基本 socket recv/send 操作。

3、evbuffer_add 和 evbuffer_remove

/**
 * @breif: 添加数据到 evbuffer 的结尾处
 *
 * @param buf: 待添加数据的 evbuffer 对象
 * @param data: 数据指针
 * @param datlen: 数据长度,单位 byte
 *
 * @return: 成功返回0,失败返回-1
 */
int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen);

/**
 * @brief: 从 evbuffer 的开始处读取指定长度的数据
 *         若 evbuffer 中的数据不足指定长度,则尽可能多的读取数据
 *
 * @param buf: 待读取数据的 evbuffer 对象
 * @param data: 数据指针
 * @param datlen: 数据长度,单位 byte
 *
 * @return: 成功返回读取的字节数,失败返回-1
 */
int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);

4、例子

#include <iostream>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <thread>
#include <errno.h>
#include <string.h>
#ifndef _WIN32
#include <signal.h>
#else
#endif
using namespace std;
#define PORT 5001

bufferevent_filter_result filter_in(evbuffer *s, evbuffer *d, ev_ssize_t limit,
    bufferevent_flush_mode mode, void *arg){
	cout<<"filter_in"<<endl;
	char data[1024] = {0};
	//读取并清理原数据
	int len = evbuffer_remove(s, data, sizeof(data) - 1);
	
	//把所有字母转成大写
	for(int i = 0; i < len; i++){
	    data[i] = toupper(data[i]);
	}
	
	evbuffer_add(d, data, len);
	return BEV_OK;
}

bufferevent_filter_result filter_out(evbuffer *s, evbuffer *d, ev_ssize_t limit,
    bufferevent_flush_mode mode, void *arg){
	cout<<"filter_out"<<endl;
	
	char data[1024] = {0};
	//读取并清理原数据
	int len = evbuffer_remove(s, data, sizeof(data) - 1);
	
	//把所有字母转成大写
	string str = "";
	str += "============\n";
	str += data;
	str += "============\n";
	
	evbuffer_add(d, str.c_str(), str.size());
	return BEV_OK;
}

void read_cb(bufferevent *bev, void *arg){
    cout<<"read_cb"<<endl;
	char data[1024] = {0};
	int len = bufferevent_read(bev, data, sizeof(data) - 1);
	cout<<data<<endl;
	//回复客户消息,经过输出过滤
	bufferevent_write(bev, data, len);
}

void write_cb(bufferevent *bev, void *arg){
    cout<<"write_cb"<<endl;
}

void event_cb(bufferevent *bev, short events, void *arg){
    cout<<"event_cb"<<endl;
}

void listen_cb(evconnlistener *ev, evutil_socket_t s, sockaddr* sin, int slen, void *arg){
    cout<<"listen_cb "<<endl;
	//创建bufferevent 绑定bufferevent filter
	event_base *base = (event_base *)arg;
	bufferevent *bev = bufferevent_socket_new(base, s, BEV_OPT_CLOSE_ON_FREE);
	//绑定bufferevent filter
	bufferevent *bev_filter = bufferevent_filter_new(bev,
	    filter_in, //输入过滤函数
		filter_out, //输出过滤函数
		BEV_OPT_CLOSE_ON_FREE, //关闭filter时同时关闭bufferevent
		0, //清理的回调函数
		0 //传递给回调的参数
		);

    //设置bufferevent的回调
	bufferevent_setcb(bev_filter, read_cb, write_cb, event_cb, NULL);
	
	bufferevent_enable(bev_filter, EV_READ|EV_WRITE);
}
int main(int argc, char *argv[])
{
#ifdef _WIN32
	WSADATA wsa;
	int a = WSAStartup(MAKEWORD(2, 2), &wsa);   
#else
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
		return 1;
#endif
    event_base *base = event_base_new();
    //创建网络服务器
	
	//设置监听的端口和地址
	sockaddr_in sin;
	memset(&sin,0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PORT);
	
	evconnlistener *ev = evconnlistener_new_bind(base,
	        listen_cb, //回调函数
			base, //回调函数的参数arg
			LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
			10, //listen back
			(sockaddr*)&sin,
			sizeof(sin)
			);
	
	//进入事件主循环
	event_base_dispatch(base);
	//释放资源
	evconnlistener_free(ev);
	event_base_free(base);
    return 0;
}

参考:

(1)libevent(十二)bufferevent filter zlib 压缩通信(二)

(2)libevent高并发网络编程 - 03_bufferevent filter过滤器

(3)Libevent 学习十一:bufferevent filter 过滤器和API

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/693527.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vscode配置终端默认为git bash

vscode配置终端默认为git bash 文章目录 vscode配置终端默认为git bashctrl shift p 打开设置添加 git bash 并设为默认终端 ctrl shift p 打开设置 添加 git bash 并设为默认终端 注意不要配置 git-bash.exe 的路径。 如果配置为 git-bash.exe 路径&#xff0c;则会单独打…

阿里云服务器ping不通如何解决?

阿里云服务器ping不通&#xff1f;什么原因&#xff1f;在安全组中允许【全部 ICMP(IPv4)】&#xff0c;当然阿里云服务器禁ping也是通过配置安全组的ICMP规则来实现的&#xff0c;阿里云服务器网来详细说下安全组开通ping功能教程&#xff1a; 目录 阿里云服务器ping不通的解…

Node Sass version 6.0.1 is incompatible with ^4.0.0问题解决

运行环境背景 操作系统&#xff1a;Windows 10 64位 node版本&#xff1a;v16.19.1 npm版本&#xff1a;8.19.3 解决方案 卸载当前版本的node-sass和node-loader npm uninstall node-sass npm uninstall node-loader 重新安装指定版本 npm i node-sass6.0.1 node-loade…

计算机图形学综述(一)

计算机已经成为快速、经济地生成图片的强大工具。实际上已经没有哪个领域不能从使用图形显示中获益&#xff0c;因此也就不奇怪为什么计算机图形学的应用是那么广泛。虽然早期的工程和科学上的应用必须依赖于昂贵而笨重的设备&#xff0c;但是计算机技术的发展已经将交互式计算…

sharding-jdbc分片功能学习笔记

sharding-jdbc是sharding-sphere下的一个模块&#xff0c;可以理解为增强版的jdbc&#xff0c;用于解决分库分表、读写分离问题&#xff0c;本文基于4.1.1版本进行说明数据分片功能的流程 该版本提供了如下功能 1.数据分片&#xff08;包括强制路由功能&#xff09; 2.读写分…

win10系统下安装qt5.12.0软件

一、软件下载 1、Qt开源社区下载 下载地址&#xff1a;https://download.qt.io/archive/qt/5.12/5.12.10/qt-opensource-windows-x86-5.12.10.exe 社区地址&#xff1a; Index of /archive/qt/5.12/5.12.10 2、百度网盘下载 链接&#xff1a;https://pan.baidu.com/s/1Sqi…

举例说明什么是卷积计算

卷积计算是一种数学运算&#xff0c;主要用于信号处理、图像处理等领域。它涉及到两个函数&#xff08;通常称为信号和核&#xff09;的互相关运算。在图像处理中&#xff0c;卷积计算通常用于实现图像的平滑、锐化、边缘检测等操作。 以图像处理为例&#xff0c;我们可以用一个…

【面试题24】MySQL如何给一个1000万的表安全的加字段

文章目录 一、前言二、MySQL表添加字段的方案2.1 ALTER TABLE 添加字段2.2 Online Alter Table2.3 Percona Toolkit2.4 给表新增字段2.5 使用触发器添加字段 总结 一、前言 本文已收录于PHP全栈系列专栏&#xff1a;PHP面试专区。 计划将全覆盖PHP开发领域所有的面试题&#xf…

【AIGC】18、MobileSAM | 首个专为移动端设计的更快的 SAM

文章目录 一、背景二、方法2.1 耦合蒸馏2.2 从半蒸馏到解耦蒸馏 三、效果 论文&#xff1a;FASTER SEGMENT ANYTHING: TOWARDS LIGHTWEIGHT SAM FOR MOBILE APPLICATIONS 代码&#xff1a;https://github.com/ChaoningZhang/MobileSAM 出处&#xff1a;韩国庆熙大学 时间&am…

MP4视频格式和mp4v2的移植

目录 1、视频文件 2、MP4 3、MP4学习方法 4、MP4文件格式解析 5、MP4Info工具使用 6、mp4v2移植和播放 6.1、下载mp4v2 6.2、配置并编译 6.3、部署 6.4、编译sample 6.5、准备TF卡 6.6、运行和测试 7、MP4打包源码解析 8.添加网络telnet调试 8.1、为什么添加teln…

java进程注入

本文重点java Instrumentation java Instrumentation指的是可以用独立于应用程序之外的代理&#xff08;agent&#xff09;程序来监测和协助运行在JVM上的应用程序。这种监测和协助包括但不限于获取JVM运行时状态&#xff0c;替换和修改类定义等。简单一句话概括下&#xff1a;…

11 通信的基本概念

目录 通信分类概览 串行通讯与并行通讯 全双工、半双工及单工通讯 同步通讯与异步通讯 通讯速率 注意 通信分类概览 串行通讯与并行通讯 串行通讯是指设备之间通过少量数据信号线(一般是 8 根以下)&#xff0c;地线以及控制信号线&#xff0c;按数据位形式一位一位地传输…

Windows下创建进程的理解

创建windows进程&#xff0c;需要考虑两个点&#xff0c;即session和权限问题。了解这两点&#xff0c;网络上服务创建界面进程&#xff0c;管理员权限进程创建普通权限进程的代码则很好理解。 1、基础知识 (1) session (2) 权限 CreateProcessAsUser需要传入一个token&#x…

LeetCode 打卡day45--完全背包问题之最小填充次数

一个人的朝圣 — LeetCode打卡第45天 知识总结Leetcode 70. 爬楼梯题目说明代码说明 Leetcode 322. 零钱兑换题目说明代码说明 Leetcode 279. 完全平方数题目说明代码说明 知识总结 今天的问题都可以归结一句话, 在完全背包的问题设置下, 问将该背包填满最少需要放几件物品. L…

java基础(并发编程)-异步模式之生产者/消费者

一、定义要点 与前面的保护性暂停中的GuardedObject不同&#xff0c;不需要产生结果和消费结果的线程一一对应消费队列可以用来平衡生产和消费的线程资源生产者仅负责产生结果数据&#xff0c;不关心数据该如何处理&#xff0c;而消费者专心处理结果数据消息队列是有容量限制的…

代码随想录算法训练营第17期第1天 | 704. 二分查找、27. 移除元素

从头开始&#xff0c;重新再来&#xff0c;但是又不完全一样&#xff0c;之前是擅长的python&#xff0c;现在是C&#xff0c;能坚持下来么&#xff1f; 704. 二分查找 704. 二分查找https://leetcode.cn/problems/binary-search/ 上次写这道题已经是两个月之前&#xff0c;说…

Openresty原理概念篇(七)OpenResty 中用到的 NGINX 知识

一 OpenResty 中用到的 NGINX 知识 Luaj 是一个 Java 的 Lua 解释器,基于 Lua 5.2.x 版本 luaj ① 说明 1) 本文可有可无原因&#xff1a;如果你之前没有接触过nginx或者涉及一点nginx,那么建议阅读2) 由于自己已经对nginx整个脉络体系进行讲解,本文只是机械的摘录,构成…

Java使用RabbitMQ实战,Springboot使用rabbitMQ实战

文章目录 一、Java原生API1、简单实例2、延迟消息3、消费端限流4、消息属性设置5、消息可靠投递 二、Spring-API1、简单实例&#xff08;1&#xff09;引入rabbitMQ.xml&#xff08;2&#xff09;生产者&#xff08;3&#xff09;消费者&#xff08;4&#xff09;测试类 三、Sp…

使用VSCODE跑orbslam2踩的坑

我用的是ubuntu22.04&#xff0c;opencv是4.7&#xff0c;使用其他的库感觉就算版本不一样&#xff0c;也能跑。 一、运行build.sh能够产生可执行文件遇到的问题 1.由于opencv版本高带来的问题 这些问题怎么定位出现在哪些文件中&#xff0c;你通过命令行&#xff0c;运行下…

更灵活的CSS3新特性:帮你简化样式管理和优化网站性能

文章目录 I. 前言&#xff1a;介绍CSS3的进化和发展趋势CSS3的历史和版本CSS3的标准化和浏览器支持情况 II. 新的CSS选择器&#xff1a;扩展选择器的功能属性选择器&#xff1a;更多方式选择元素伪类和伪元素&#xff1a;更方便地定义样式 III. 改进的排版和布局&#xff1a;实…