libevent 库上手

先来看一个基于定时器的事件驱动

#include <stdio.h>
#include <event.h>

void onTime(int sock, short event, void* arg) {
    printf("hi there\n");
    struct timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    event_add((struct event*)arg, &tv);
}

int main() {
    event_init();
    struct event evTime;
    evtimer_set(&evTime, onTime, &evTime);
    struct timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    event_add(&evTime, &tv);
    event_dispatch();
    return 0;
}

可以看到流程还是比较清晰简单的,下面再看一个 socket 事件的回调

#include <stdio.h>
#include <assert.h>
#include <event.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

struct event_base* base;

void onRead(int iCliFd, short iEvent, void* arg) {
    char buf[8192];
    int iLen = recv(iCliFd, buf, 8192, 0);
    if (iLen <= 0) {
        printf("cli close\n");
        struct event* pEvRead = (struct event*)arg;
        event_del(pEvRead);
        delete pEvRead;

        close(iCliFd);
        return;
    }
    buf[iLen] = 0;
    printf("cli info:\n------------------------\n%s------------------------\n", buf);
}

void onAccept(int iSvrFd, short iEvent, void* arg) {
    struct sockaddr_in stCliAddr;
    socklen_t iSinSize = sizeof(stCliAddr);
    int iCliFd = accept(iSvrFd, (struct sockaddr*)&stCliAddr, &iSinSize);
    struct event* pEvRead = new event;
    event_set(pEvRead, iCliFd, EV_READ|EV_PERSIST, onRead, pEvRead);
    event_base_set(base, pEvRead);
    event_add(pEvRead, NULL);
}

int main() {
    int iSvrFd = socket(AF_INET, SOCK_STREAM, 0);
    assert(iSvrFd != -1);
    struct sockaddr_in stSvrAddr;
    memset(&stSvrAddr, 0, sizeof(stSvrAddr));
    stSvrAddr.sin_family = AF_INET;
    stSvrAddr.sin_addr.s_addr = INADDR_ANY;
    stSvrAddr.sin_port = htons(8080);
    assert(bind(iSvrFd, (struct sockaddr*)&stSvrAddr, sizeof(stSvrAddr)) != -1);
    assert(listen(iSvrFd, 10) != -1);
    
    base = event_base_new();
    struct event evListen;
    event_set(&evListen, iSvrFd, EV_READ|EV_PERSIST, onAccept, NULL);
    event_base_set(base, &evListen);
    event_add(&evListen, NULL);
    event_base_dispatch(base);

    return 0;
}

附上 Makefile

INC += -I/home/adenzhang/tools/libevent-2.0.21-stable/include/

LIB += -L/home/adenzhang/tools/libevent-2.0.21-stable/lib/ -levent

all:
	g++ -g -Wall -o libevent_time_echo libevent_time_echo.cpp $(INC) $(LIB)
	g++ -g -Wall -o libevent_tcp_echo libevent_tcp_echo.cpp $(INC) $(LIB)

一开始编译的时候报 event_base_new 函数没有实现,后来才发现是机器上的库的版本太老,使用这个命令可以看到链接时使用的具体文件

gcc -print-file-name=libevent.so

下载一个 2.x 的库就可以了,安装也就是 ./configure && make && make install 三部曲,挺顺利没有遇到问题

对于 libevent 的基本理解可以看到这里,http://www.cnblogs.com/cnspace…,详细的源码分析看到这里,http://blog.csdn.net/sparklian…

其实可以看到,libevent 在写 socket 上,跟 epoll 的感觉还是差不多的,而实际上 libevent 在 linux 上也是基于 epoll 的,那么其实可以直接用 epoll,如果在不考虑可移植性的情况下。

5 thoughts on “libevent 库上手

    • node js 那么潮爆的东西,还是自己的 weekend 项目用用就算了,在生产环境还是别想了,为了稳定,保守到什么程度,看着 c++11 和 boost 的智能指针封装好了干着急不能用,想要 RAII?自己写封装。代码写起来累点苦力点没关系,甚至运行效率低点也可以堆机器,但是服务器上跑了六七年的代码改一下都要很小心,引入新的第三方库都要评估,何况换语言。。

      • 不是用 Node.js 啊,是用 libuv 啊~设计的很不错的库~

        而且源码量也不大,自己大概浏览一遍就有安全感了 : )

        • 搜了一下看到云风的 blog 有说道,看起来还行。。不过我们最终的生产环境还是没有用第三方库,自己写了事件驱动。。真是造轮子。。

          • 自己造轮子如果造得圆还好了…… 我比较受不了放着开源的不用自己造轮子,造出来还是方的……

Leave a Reply to ZRJ Cancel reply

Your email address will not be published. Required fields are marked *