Libevent (15) bufferevent filter filter y ejemplos

1. Breve descripción del filtro bufferevent

Algo así como filter, creo que los programadores con experiencia en php framework o java springboot deberían estar familiarizados con él, es un procesador cargado antes del flujo de entrada o después del flujo de salida, que se usa para separarse del negocio para hacer algunas cosas extra.

(1) Los datos leídos (recibidos) primero ingresan al filtro y luego se los pasan al usuario para que los lea después de procesar el filtro, es decir, antes de que se lea el filtro, por ejemplo, los datos comprimidos primero deben descomprimirse en el y luego en el subyacente Lee el original descomprimido;
(2) Los datos escritos (enviados) son iniciados por el usuario, luego pasan al filtro y luego se envían después de que se procesa el filtro, es decir, después de que el filtro está escrito, como el original enviado en el subyacente Los datos se comprimirán en el filtro antes de enviar.

二, API de evento de búfer

1、bufferevent_filter_nuevo

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);

Función de devolución de llamada 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. estructura de evbuffer

Esta estructura se utiliza para transferir datos entre el evento de búfer de filtro y el evento de búfer subyacente.

(1) evbuffer es solo un búfer de datos, implementado usando una lista enlazada, sin ninguna operación de E/S.
(2) bufferevent es una E/S de búfer de eventos, que implementa operaciones básicas de recepción/envío de socket internamente.

3, evbuffer_add y 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. Ejemplos

#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;
}

referencia:

(1) libevent (12) bufferevent filtro comunicación de compresión zlib (2)

(2) programación de red concurrente alta libevent - filtro de filtro 03_bufferevent

(3) Libevent Learning Eleven: filtro de filtro de eventos de búfer y API

Supongo que te gusta

Origin blog.csdn.net/mars21/article/details/131414432
Recomendado
Clasificación