bufferevent_filter_new对缓冲区数据过滤(解压加密)

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);
  1. 缓冲区对象上下文
  2. 输入缓冲区过滤回调函数
  3. 输出缓冲区过滤回调函数
  4. flag
  5. 回调函数
  6. 过滤回调函数的参数

能够对收发的数据做业务上的处理,比如压缩,加密等。加密解密是通过内存性能换取网络带宽的节约,实现了业务的解耦

减少对缓冲区的复制,类似于sendfile零拷贝接口。

evbuffer_peek底层是个链表从缓冲区读取数据,因为具体到读多少数据需要用户自己决定,或者由函数内部自动链起来缓冲。

直接读取缓冲数据不复制,然后经过业务处理后,再从缓冲区抽掉该部分数据对应的大小,就像水位一样,抽掉水池的水。

zlib对于网络传输数据的压缩,因为TCP是流式的,每次连接接收到的字节数都难以确定边界,每个数据包又会不同,所以zlib提供了适合网络传输的相关函数

deflateInit(z_stream* ,int level)

  • z_stream结构体用于提供交互的,存储了空间大小,剩余大小等
  • level压缩等级
  • Z_DEFAULT_COMPRESSION
  • Z_BEST_COMPRESSION
  • Z_BEST_SPEED
  • returns Z_OK
  • Z_SYNC_FLUSH刷新输出缓冲区,字节边界对齐

int deflate(z_stream* strm,int flush)

  • uInt avail_in源空间
  • Bytef *next_in输入空间地址
  • uInt avail_out输出空间大小,处理后就是剩余空间大小
  • Bytef *next_out输出空间地址
 shared_ptr<FILE> myFileList(fp,&fclose);
    // 初始化zlib上下文
    shared_ptr<z_stream> z_output (new z_stream());
    deflateInit(z_output.get(),Z_DEFAULT_COMPRESSION); // 选择默认的压缩方式
z_output->avail_in = v_in[0].iov_len;           // 输入数据的大小
    z_output->next_in =(Byte*) v_in[0].iov_base;    // 输入数据的地址
                                                    // 申请输出空间大小
    evbuffer_iovec v_out[1];
    evbuffer_reserve_space(dst,1024,v_out,1);
                                                    // zlib的输出空间大小
    z_output->avail_out = v_out[0].iov_len;

                                                    // zlib的输出空间大小
	z_output->next_out =(Byte*) v_out[0].iov_len;
	evbuffer_add(dst,str.c_str(),str.size());

master.hpp master.cpp

#ifndef __MASTER_HPP__
#define __MASTER_HPP__
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>
 
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#include "filter.hpp"
#define PORT 5002
using namespace std;
class Cwork
{
    public:
    Cwork()
    {
        memset(&m_sin,0,sizeof(m_sin));
        m_sin.sin_family = AF_INET;
        m_sin.sin_port = htons(PORT);
    }
    ~Cwork()
    {
        event_base_free(m_base);
        evconnlistener_free(m_ev);
    }
    void init();
    void run();
   static void listen_cb(struct evconnlistener *m_ev, evutil_socket_t fd, struct sockaddr * serv_sock, int socklen, void *arg);
private:
    event_base* m_base;
    sockaddr_in m_sin;
    evconnlistener* m_ev;
    
};
class event_cb
{
    public:
    static void sread_cb(bufferevent *be,void *arg);
    static void swrite_cb(bufferevent *be,void *arg);
    static void events_cb(bufferevent *be,short events,void *arg); // 参数2 需要区分事件类型
};
#endif
#include "master.hpp"
void Cwork::listen_cb(struct evconnlistener *m_ev, evutil_socket_t fd, struct sockaddr * serv_sock, int socklen, void *arg)
{
    cout<<"listen "<<endl;
    event_base* base = (event_base*)arg;
    bufferevent *bev = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);

    bufferevent_enable(bev,EV_READ|EV_WRITE);

    bufferevent *bev_filter = bufferevent_filter_new(bev,
    Filter::fileter_in,
    Filter::fileter_out,
    BEV_OPT_CLOSE_ON_FREE,
    0,
    0);
    // 注册过滤器
    
    bufferevent_setcb(bev_filter,event_cb::sread_cb,event_cb::swrite_cb,event_cb::events_cb,NULL);
    
    bufferevent_enable(bev_filter,EV_READ|EV_WRITE); // 开启读写权限 
}

void Cwork::init()
{
    m_base = event_base_new();
    // 创建上下文

    m_ev = evconnlistener_new_bind(m_base,
		Cwork::listen_cb,		//回调函数
		m_base,			//回调函数的参数arg
		LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
		10,				//listen back
		(sockaddr*)&m_sin,
		sizeof(m_sin)
		);
    
}
void Cwork::run()
{
    event_base_dispatch(m_base);
}
void event_cb::sread_cb(bufferevent *be,void *arg)
{
    char data[1024] = {0};
	//读取输入缓冲数据
	int len = bufferevent_read(be,data,sizeof(data)-1);
	cout<<"["<<data<<"]"<<endl;
	if(len<=0)return;
	if(strstr(data,"quit") !=NULL)
	{
		cout<<"quit";
		//退出并关闭socket BEV_OPT_CLOSE_ON_FREE
		bufferevent_free(be);
	}
	//发送数据 写入到输出缓冲
	bufferevent_write(be,"OK\n",5);
}
void event_cb::swrite_cb(bufferevent *be,void *arg)
{
    cout<<"[W]"<<endl;
}
void event_cb::events_cb(bufferevent *be,short events,void *arg)
{
    if(events & BEV_EVENT_TIMEOUT)
    {
        cout<<"timeout"<<endl;
        bufferevent_enable(be,EV_READ|EV_WRITE); // 超时可以重新将其纳入事件监听,如果可以,那就设置如果一个连接超时了三次
        // bufferevent_free(be);
    }
    else if(events & BEV_EVENT_ERROR)
    {
        cout<<"close()"<<endl;
        bufferevent_free(be); // 设置了关闭
    }
    cout<<"[E]"<<flush;	
}

filter.cpp filter.hpp

#ifndef __FILTER_HPP__
#define __FILTER_HPP__
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>

using namespace std;
class Filter
{
    public:
    static bufferevent_filter_result fileter_out(struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit,enum bufferevent_flush_mode mode, void *ctx);
    static bufferevent_filter_result fileter_in(struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit,enum bufferevent_flush_mode mode, void *ctx);
};
#endif
#include "filter.hpp"
bufferevent_filter_result Filter::fileter_out(struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit,enum bufferevent_flush_mode mode, void *ctx)
{
    cout<<"filter_out"<<endl;
	char data[1024] = {0};
	//读取并清理原数据
	int len = evbuffer_remove(src,data,sizeof(data)-1);

	string str = "";
	str += "================\n";
	str += data;
	str += "================\n";
	evbuffer_add(dst,str.c_str(),str.size());

	return BEV_OK;
}
bufferevent_filter_result Filter::fileter_in(struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit,enum bufferevent_flush_mode mode, void *ctx)
{
    cout<<"filter_in"<<endl;
	
	char data[1024] = {0};
	//读取并清理原数据
	int len = evbuffer_remove(src,data,sizeof(data)-1);

	//所有字母转成大写
	for (int i = 0; i < len; ++i)
	{
		data[i] = toupper(data[i]);
	}

	evbuffer_add(dst,data,len);
	return BEV_OK;
}

main.cpp

#include "master.hpp"



int main(int argc,char *argv[])
{
	//忽略管道信号,发送数据给已关闭的socket
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
		return 1;
	
	//进入事件主循环
	
	Cwork *cwork = new Cwork();
    cwork->init();
    cwork->run();
    delete cwork;
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值