libevent4:事件

事件状态

事件状态主要分为:
已初始化(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:事件

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动到顶部