事件状态
事件状态主要分为:
已初始化(initialized):调用event_new之后 no-pending状态
待决(pending):调用event_add之后
激活(avtive):事件发生,包括超时事件
持久(persistent):如果没设置这个,触发事件后就回到no-pending。如果设定了这个就处于pending状态。
监听信号事件(linux)
git地址:http://121.4.70.4:3000/adminPyf/libevent_study.git
libevent_study/test_signal
#include <iostream>
#include <event2/event.h>
#include <signal.h>
using namespace std;
//sock 文件描述符 which 事件类型 arg传递的参数
static void Ctrl_C(int sock,short which , void* arg){
cout << "Ctrl_C" << endl;
}
static void Kill(int sock,short which , void* arg){
cout << "Kill" << endl;
event *ev = (event*)arg;
//如果处于非待决
if(!evsignal_pending(ev,NULL)){
event_del(ev);
event_add(ev,NULL); //再次添加进来
}
}
int main(int agrc,char** agrv){
event_base *base = event_base_new();
//添加信号 ctrl+c ,处于no pending 状态
//evsignal_new 隐藏的状态 EV_SIGNAL|EV_PERSIST
event *csig = evsignal_new(base,SIGINT,Ctrl_C,base);
if(!csig){
cerr << "SIGNAL evsignal_new failed!" << endl;
return -1;
}
if (event_add(csig,0) != 0){
cerr << "SIGANL event_add failed" << endl;
}
//添加kill信号
//非持久事件,只进入一次 event_self_cbarg()传递当前的event
event *ksig = event_new(base,SIGTERM,EV_SIGNAL,Kill,
event_self_cbarg());
if(!ksig){
cerr << "SIGNAL evsignal_new failed!" << endl;
return -1;
}
if (event_add(ksig,0) != 0){
cerr << "SIGANL event_add failed" << endl;
}
//进入事件主循环
event_base_dispatch(base);
event_free(csig);
event_free(ksig);
event_base_free(base);
return 0;
}
监听定时器事件(linux)
git地址:http://121.4.70.4:3000/adminPyf/libevent_study.git
libevent_study/test_timer
#include <iostream>
#include <event2/event.h>
#include <string.h>
#include <thread>
#ifdef _WIN32
#else
#include <signal.h>
#endif // !_WIN32
using namespace std;
static timeval t1 = {1,0};
void timer1(int sock,short which, void *arg){
cout << "[timer1]" << flush;
event* ev = (event*)arg;
if(!evtimer_pending(ev,&t1) ){
evtimer_del(ev);
evtimer_add(ev,&t1);
}
}
void timer2(int sock,short which, void *arg){
cout << "[timer2]" << flush;
this_thread::sleep_for(3000ms); //c++ 11
}
void timer3(int sock,short which, void *arg){
cout << "[timer3]" << flush;
}
int main(int agrc,char** agrv){
#ifdef _WIN32
//初始化socket库
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
#else
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { //忽略管道信号,发送数据给已关闭的socket,会飞掉!
return 1;
}
#endif
event_base *base = event_base_new();
//定时器
cout << "test timer" << endl;
//非持久定时器 只进入一次
event* evl = evtimer_new(base ,timer1,event_self_cbarg());
if(evl == NULL){
cout << "evtimer_new timer1 failed!" <<endl;
return -1;
}
evtimer_add(evl,&t1);
static timeval t2;
t2.tv_sec = 1;
t2.tv_usec = 200000; //微秒
event *ev2 = event_new(base,-1,EV_PERSIST,timer2,0);
event_add(ev2,&t2);
//超时性能优化,默认event用二叉堆存储,插入删除 时间复杂度为O(logN)
//优化到双向队列 插入删除O(1)
event *ev3 = event_new(base,-1,EV_PERSIST,timer3,0);
static timeval tv_in = {3,0};
const timeval * t3;
t3 = event_base_init_common_timeout(base,&tv_in);
event_add(ev3,t3);
//进入事件主循环
event_base_dispatch(base);
event_free(evl);
event_free(ev2);
event_base_free(base);
return 0;
}
监听文件改变事件
git地址: http://121.4.70.4:3000/adminPyf/libevent_study.git
libevent_study/test_file
#include <iostream>
#include <event2/event.h>
#include <string.h>
#include <thread>
#ifdef _WIN32
#else
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif // !_WIN32
using namespace std;
void read_file(evutil_socket_t fd,short event,void *arg){
char buf[1024] = {0};
int len = read(fd,buf,sizeof(buf) - 1);
if(len > 0){
cout << buf << endl; // 当有用户登录就会把 该信息打印出来
}else {
cout << "." << endl;
this_thread::sleep_for(500ms);
}
}
int main(int agrc,char** agrv){
#ifdef _WIN32
//初始化socket库
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
#else
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { //忽略管道信号,发送数据给已关闭的socket,会飞掉!
return 1;
}
#endif
event_config* conf = event_config_new();
event_config_require_features(conf,EV_FEATURE_FDS);
event_base *base = event_base_new_with_config(conf);
event_config_free(conf);
if(!base){
cerr << "event_base_new_with_config failed" <<endl;
}
int sock = open("/var/log/auth.log",O_RDONLY|O_NONBLOCK,0);
if(sock < 0){
cerr << "/var/log/auth.log open failde" << endl;
}
lseek(sock,0,SEEK_END);
//监听文件数据
event* fev = event_new(base,sock,EV_READ|EV_PERSIST ,read_file,0);
event_add(fev,NULL);
//进入事件主循环
event_base_dispatch(base);
event_free(fev);
event_base_free(base);
return 0;
}
监听网络服务器事件!!
git地址: http://121.4.70.4:3000/adminPyf/libevent_study.git
libevent_study/test_event_server
#include <iostream>
#include <event2/event.h>
#include <string.h>
#include <thread>
#include <errno.h>
#define SPORT 5001
#ifdef _WIN32
#else
#include <signal.h>
#endif // !_WIN32
using namespace std;
//正常断开连接也会进入 超时会进入
void client_cb(evutil_socket_t s,short w,void *arg){
//水平触发LT 只要有数据没处理会 一直进入
//边缘触发ET 有数据时只触发一次
event *ev = (event *) arg;
if(w&EV_TIMEOUT){
cout << "timeout" << endl;
//需要清理event
event_free(ev);
evutil_closesocket(s);
return;
}
char buf[1024]= {0};
int len = recv(s,buf,sizeof(buf)-1,0);
if(len > 0){
cout << buf << flush;
send(s,"ok",2,0);
}
else{
//需要清理event
cout << "event_free" << endl;
event_free(ev);
evutil_closesocket(s);
}
}
void listen_cb(evutil_socket_t s,short w,void *arg){
cout << "listen_cb" << endl;
sockaddr_in sin;
socklen_t size = sizeof(sin);
//读取连接信息
evutil_socket_t client = accept(s,(sockaddr*)&sin,&size);
char ip[16] = {0};
evutil_inet_ntop(AF_INET,&sin.sin_addr,ip,sizeof(ip)-1);
cout << "client ip is " << ip << endl;
//客户端数据读取事件
event_base *base = (event_base*)arg;
event *ev = event_new(base,client,EV_READ|EV_PERSIST ,client_cb,event_self_cbarg());
timeval t = {10,0};
event_add(ev,&t);
}
int main(int agrc,char** agrv){
#ifdef _WIN32
//初始化socket库
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
#else
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { //忽略管道信号,发送数据给已关闭的socket,会飞掉!
return 1;
}
#endif
event_base *base = event_base_new();
cout << "test event server" << endl;
evutil_socket_t sock = socket(AF_INET,SOCK_STREAM,0);
if(sock == 0){
cout << "socket error:" << strerror(errno) << endl;
return -1;
}
//绑定端口地址
sockaddr_in sin;
memset(&sin,0,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(SPORT);
int re = ::bind(sock,(sockaddr*)&sin,sizeof(sin));
if(re != 0){
cerr << "bind error: " << strerror(errno) << endl;
return -1;
}
//设置地址复用和非阻塞
evutil_make_socket_nonblocking(sock);
evutil_make_listen_socket_reuseable(sock);
//开始监听
listen(sock,10);
//开始接收连接事件
event *ev = event_new(base,sock,EV_READ|EV_PERSIST /* |EV_ET*/ ,listen_cb,base); //默认水平触发
event_add(ev,0);
//进入事件主循环
event_base_dispatch(base);
evutil_closesocket(sock);
event_base_free(base);
return 0;
}
libevent4:事件