zoukankan      html  css  js  c++  java
  • libevent的使用

    一:libevent的编译安装

    (一)下载地址

    https://libevent.org/

    (二)编译安装

    ./configure --prefix=/usr/local/libevent
    sudo make && sudo make install

    二:libevent基础知识学习

    (一)重要函数

    struct event_base *event_base_new(void);
    功能:函数会检测环境变量,返回一个event_base的指针,分配并且返回一个新的具有默认设置的 event_base。类似epoll使用中的epoll_create(用于创建epoll实例),这里用于创建libevent实例,还初始化libevent管理相关的代码,比如队列创建
    int event_base_dispatch(struct event_base *);
    功能:事件触发,一旦创建好事件根基event_base,并且在根基上安插好事件之后,需要对事件循环监控(换句话说就是等待事件的到来,触发事件的回调函数)

    (二)事件处理相关(底层)

    (三)事件处理相关(高层)

    evconnlistener_new_bind方法:

    第一个参数代表主事件,也就是创建的event_base;

    第二个参数代表回调函数,触发可读事件之后,返回给我们需要的信息

    第三个参数代表需要额外传递给回调函数的参数

    第四个参数代表标志位,比如:

    LEV_OPT_REUSEABLE设置地址复用,內部函数原型应该是setsocketopt(sockfd, SOL_SOCKET, SO_RESUEADDR, on, sizeof(on)) 
    LEV_OPT_CLOSE_ON_FREE代表连接开闭時同事开关底层套接字

    第五个参数代表监听的最大数量(毫秒级别),如果设置为-1系统将选择一个合适的数值,如果為-1,內部实现的数值为128(固定的)跟SOMAXCONN一样的值

    第六个参数代表需要綁定的地址

    第七个参数代表地址的大小

    函数內部创建了一個listenfd,根据你的參数是否设置为非阻塞(evutil_make_socket_nonblocking())函数进行设置,这个函数的內部为fcntl函数(flags=fcntl(fd, F_GETFL), flags |= O_NONBLOCK, fcntl(fd, F_SETFL, flags))进行设置,然后进行地址绑定(bind()),再创建一個evconnlistener *类型的对象,用evconnlistener_new()函数來进行创建,evconnlistener_new()函数內部进行监听(listen()),创建一个evconnlistener_event的監聽事件,將主事件,listenfd,回调函数,evconnlistener_event进行綁定。這個回调函数為listener_read_cb函数,當着個函数被调用的時候,內部进行accept一個connfd,进而调用我们自己的回调函数read/write等操作。

    (四)缓冲区数据结构

    1.bufferevent_socket_new:使用bufferevent_socket_new创建一个struct bufferevent *bev,关联该sockfd,托管给event_base

    struct bufferevent * bufferevent_socket_new(struct event_base *base, evutil_socket_t fd,  int options)  

    2.bufferevent_enable:启用读写事件,其实是调用了event_add将相应读写事件加入事件监听队列poll

    int bufferevent_enable(struct bufferevent *bufev, short event)  

    3.bufferevent_setcb回调函数:

    void bufferevent_setcb(struct bufferevent *bufev,
        bufferevent_data_cb readcb, bufferevent_data_cb writecb,bufferevent_event_cb eventcb, 
    void *cbarg);
    在readcb里面从input中读取数据,处理完毕后填充到output中;
    
    writecb对于服务端程序,只需要readcb就可以了,可以置为NULL;
    
    errorcb用于处理一些错误信息

    4.evbuffer_add_buffer:从一个evbuffer 向另一个evbuffer移动数据

    函数evbuffer_add_buffer()将src中的所有数据移动到dst末尾,成功时返回0,失败时返回-1
    evbuffer_add_buffer(output,input);             //把输入的数据,添加到输出队列中去。当写事件触发后,就会去输出缓冲区中读取数据发送给系统底层

    三: 使用libevent实现高性能服务器

    #include <iostream>
    #include <event2/listener.h>
    #include <event2/buffer.h>
    #include <event2/bufferevent.h>
    
    #include <arpa/inet.h>
    
    #define PORT 8080
    
    void on_read_cb(struct bufferevent* bev,void* ctx)
    {
        struct evbuffer *input=NULL;
        struct evbuffer *output=NULL;
        input = bufferevent_get_input(bev);
        output = bufferevent_get_output(bev);
        evbuffer_add_buffer(output,input);             //把输入的数据,添加到输出队列中去。当写事件触发后,就会去输出缓冲区中读取数据发送给系统底层
    }
    
    void on_accept_cb(struct evconnlistener* listener,
                      evutil_socket_t fd,
                      struct sockaddr* addr,
                      int socklen,
                      void* ctx)
    {
        struct event_base *base = NULL;
        struct bufferevent *bev = NULL;
    
        base = evconnlistener_get_base(listener);
        bev = bufferevent_socket_new(base,fd,0);    //使用bufferevent_socket_new创建一个structbufferevent *bev,关联该sockfd,托管给event_base
    
        bufferevent_enable(bev,EV_READ | EV_WRITE);
        bufferevent_setcb(bev,on_read_cb,NULL,NULL,NULL);
    }
    
    int main(int argc,char* argv[])
    {
        struct sockaddr_in serveraddr;
    
        struct event_base *base = NULL;
        struct evconnlistener *listener = NULL;
    
        base = event_base_new();
    
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_port = htons(PORT);
        serveraddr.sin_addr.s_addr = INADDR_ANY;
    
        listener = evconnlistener_new_bind(base,
                                on_accept_cb,
                                NULL,
                                LEV_OPT_REUSEABLE,
                                10,
                                (struct sockaddr*)&serveraddr,
                                sizeof(serveraddr));
    
        event_base_dispatch(base);
    
        return 0;
    }

    编译:

    g++ -g libevent_ln.cpp -o ll `pkg-config --libs --cflags libevent`
  • 相关阅读:
    严重: Parse error in application web.xml file at jndi:/localhost/ipws/WEBINF/web.xml java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml
    Failed to install .apk on device 'emulator5554': timeout解决方法
    java.lang.NoClassDefFoundError:org.jsoup.Jsoup
    Conversion to Dalvik format failed: Unable to execute dex:解决方法
    apache Digest: generating secret for digest authentication ...
    Description Resource Path Location Type Project has no default.properties file! Edit the project properties to set one.
    android service随机自启动
    MVC3 安装部署
    EF 4.3 CodeBased 数据迁移演练
    SQL Server 2008开启sa账户
  • 原文地址:https://www.cnblogs.com/ssyfj/p/14837436.html
Copyright © 2011-2022 走看看