Libevent 事件過濾器
阿新 • • 發佈:2021-01-03
#include "event2/listener.h"
#include <error.h>
#include <string.h>
#include "event.h"
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <event2/bufferevent.h>
#include <event2/bufferevent_struct.h>
#include <event2/buffer.h>
#include <event2/util.h>
#include <ctype.h>
//回撥函式(*bufferevent_filter_cb)
bufferevent_filter_cb filter_in(struct evbuffer *evs, struct evbuffer *evd, ev_ssize_t limit, enum bufferevent_flush_mode mode, void* arg)
{
int i;
printf("filter_in\n" );
char data[1024]={0};
//讀取並清理原資料
int len=evbuffer_remove(evs,data,sizeof(data)-1);
for( i=0;i<len;i++)
{
data[i]=toupper(data[i]);
}
evbuffer_add(evd,data,len);
return BEV_OK;
}
bufferevent_filter_cb filter_out(struct evbuffer *evs, struct evbuffer *evd, ev_ssize_t limit, enum bufferevent_flush_mode mode, void* arg)
{
printf("filter_out\n");
char data[1024]={0};
int len=evbuffer_remove(evs,data,sizeof(data)-1);
evbuffer_add(evd,data,len);
return BEV_OK;
}
//typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx);
void write_cb(struct bufferevent *bev, void *ctx)
{
printf("write_cb\n");
/* char buf[128];
fgets(buf,sizeof(buf),stdin);
int ret=bufferevent_write(bev,buf,strlen(buf));
if(ret==0)
{
printf("write success\n");
}*/
}
void read_cb(struct bufferevent *bev, void *ctx) // @return 0 if successful, or -1 if an error occurred.
{
printf("read_cb\n");
char buf[1024]={0};
//int fd=*(int *)ctx;
size_t ret=bufferevent_read(bev,buf,sizeof(buf));
if(ret<0)
{
perror("read error");
exit(1);
}else bufferevent_write(bev,buf,ret);
}
//有異常發生的回撥函式
//typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short what, void *ctx);
void event_cb(struct bufferevent *bev, short what, void *ctx)
{
printf("what!!! %x\n",what);
if(what&BEV_EVENT_EOF)
{
printf("客戶端%d下線\n",*(int *)ctx);
bufferevent_free(bev);//釋放bufferevent 物件
}else
{
printf("未知錯誤\n");
}
}
void listencallback(struct evconnlistener *evlisten, evutil_socket_t fd, struct sockaddr *addr, int socklen,void *arg)
{
printf("callbcak\n");
//針對 異常存在的 sockket建立 bufferevent 物件
/*struct bufferevent *bufferevent_socket_new(struct event_base *base,
* evutil_socket_t fd, int options);
*/
struct event_base *base =arg;
//如果bufferevent 物件 被釋放 就關閉檔案描述符
// BEV_OPT_CLOSE_ON_FREE ruguo bufferevent dui xiang bei shifang jiu guan bi wen jian miao shu fu
//BEV_OPT_THREADSAFE
//BEV_OPT_DEFER_CALLBACKS
//BEV_OPT_UNLOCK_CALLBACKS
struct bufferevent *bufferev=bufferevent_socket_new(base, fd,BEV_OPT_CLOSE_ON_FREE );
if(bufferev==NULL) {
perror("bufferevent_socket_new error");
exit(1);
}
//filter
struct bufferevent *bev_filter=bufferevent_filter_new(bufferev,
(bufferevent_filter_cb)filter_in,
(bufferevent_filter_cb)filter_out,
BEV_OPT_CLOSE_ON_FREE,
0,//清理的回撥函式
0);
bufferevent_setcb(bev_filter,read_cb,write_cb,event_cb,NULL);
//使能bufferevent物件
bufferevent_enable(bev_filter,EV_READ|EV_WRITE);
}
int main(int argc, char *argv[])
{
/*socket bind listen accept*/
//用 evconnlistener_new_bind一步到位
struct event_base *base=event_base_new(); //建立時間集合
if(base==NULL)
{
perror("base create error");
exit(1);
}
// evconnlistener_cb cb ----------- 當一個新的連線到達就會呼叫回撥函式
// void *ptr -----回撥函式的引數
//unsigned flags ------------預設為NULL
// LEV_OPT_LEAVE_SOCKETS_BLOCKING 阻塞等待
//LEV_OPT_CLOSE_ON_FREE 釋放監聽物件的時候關閉sokcet
// LEV_OPT_REUSEABLE socket 關閉的時候埠可以重複使用
//int backlog----監聽佇列長度
struct sockaddr_in server;
memset(&server,0,sizeof(server));
server.sin_port=ntohs(8888);
server.sin_addr.s_addr=inet_addr("127.0.0.1");
server.sin_family=AF_INET;
//釋放監聽物件關閉soket |埠重複使用
//sockt fd 會加到集合base中去
struct evconnlistener *evlisten=evconnlistener_new_bind(base,listencallback,
base,LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,10,(struct sockaddr*)&server,sizeof(server));
if(evlisten==NULL)
{
perror("evconnlistener_new_bind error");
exit(1);
}
printf(" accept success\n");
//監聽
event_base_dispatch(base);
// 釋放 物件
evconnlistener_free(evlisten);
//釋放集合
event_base_free(base);
return 0;
}
和客戶端通訊 結果
伺服器:
客戶端: