• 个人笔记(4)


    最近几天一直在看libevent的源代码。

    看的方法是:

      ①网络上一些大牛的博客资料

      ②libevent源代码(版本:Libevent 2.0.16-stable)

      ③libevent例子程序

      ④libevent相关文档

    特别推荐的学习资料是张亮大牛的Blog:http://blog.csdn.net/sparkliang/article/category/660506

    跟着这个资料,再动手调一下库中自带的例子程序,你很容易就能够了解libevent的事件处理流程。

    下面是一个对例子程序hello-world.c写的一个client程序:

     1 /* Don't actually copy this code: it is a poor way to implement an
     2    HTTP client.  Have a look at evhttp instead.
     3 */
     4 #include <event2/bufferevent.h>
     5 #include <event2/buffer.h>
     6 #include <event2/event.h>
     7 #include <sys/socket.h>
     8 #include <string.h>
     9 #include <stdio.h>
    10 
    11 void readcb(struct bufferevent *bev, void *ptr)
    12 {
    13     char buf[1024];
    14     int n;
    15     struct evbuffer *input = bufferevent_get_input(bev);
    16     while ((n = evbuffer_remove(input, buf, sizeof(buf))) > 0) 
    17     {
    18         fwrite(buf, 1, n, stdout);
    19     }
    20 }
    21 
    22 void eventcb(struct bufferevent *bev, short events, void *ptr)
    23 {
    24     if (events & BEV_EVENT_CONNECTED) 
    25     {
    26         printf("Connect okay.\n");
    27     } 
    28     else if (events & (BEV_EVENT_ERROR|BEV_EVENT_EOF)) 
    29     {
    30         struct event_base *base = (struct event_base *)ptr;
    31         if (events & BEV_EVENT_ERROR) 
    32         {
    33             printf("BEV_EVENT_ERROR\n");
    34         }
    35         printf("Closing\n");
    36         bufferevent_free(bev);
    37         event_base_loopexit(base, NULL);
    38     }
    39 }
    40 
    41 int main(int argc, char **argv)
    42 {
    43     struct event_base *base;
    44     struct bufferevent *bev;
    45     struct sockaddr_in sin;
    46 
    47     base = event_base_new();
    48     
    49     memset(&sin, 0, sizeof(sin));
    50     sin.sin_family = AF_INET;
    51     sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
    52     sin.sin_port = htons(9995);
    53 
    54     bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
    55     //set callback function
    56     bufferevent_setcb(bev, readcb, NULL, eventcb, base);
    57     //enable read event
    58     bufferevent_enable(bev, EV_READ);
    59     //disabel write event
    60     bufferevent_disable(bev, EV_WRITE);
    61     
    62     if (bufferevent_socket_connect(bev,(struct sockaddr *)&sin, sizeof(sin)) < 0) 
    63     {
    64         bufferevent_free(bev);
    65         return -1;
    66     }
    67     
    68     event_base_dispatch(base);
    69     
    70     return 0;
    71 }

    通过这个例子可以知道,libevent在处理事件的大体过程是:

    ①通过event_base_new()创建一个event_base实例

    ②通过event_add()(这里使用的是bufferevent_socket_new())将一个event绑定到一个base

    ③设置相应的I/O事件回调函数(读写事件),信号事件回调函数,超时事件回调函数等参数

    ④调用event_base_dispatch()进入事件主循环,其间触发什么事件,就调用相应的事件回调函数进行处理

    其他:

    ①libevent用到的基本数据结构主要是双向链表和最小堆,用双向链表存储事件,用最小堆处理超时

    ②libevent根据系统选择处理异步IO的方法,可以通过相关API查询系统支持的方法,例如:

     1 #include <event2/event.h>
     2 #include <stdio.h>
     3 
     4 int main(int argc, char *argv[])
     5 {
     6     int i;
     7     const char **methods = event_get_supported_methods();
     8     printf("Starting Libevent %s.  Available methods are:\n", event_get_version());
     9     
    10     for (i=0; methods[i] != NULL; ++i) 
    11     {
    12         printf("    %s\n", methods[i]);
    13     }
    14     
    15     struct event_base *base;
    16     enum event_method_feature f;
    17 
    18     base = event_base_new();
    19     if (!base) 
    20     {
    21         puts("Couldn't get an event_base!\n");
    22     } 
    23     else 
    24     {
    25         printf("Using Libevent with backend method %s.", event_base_get_method(base));
    26         f = (enum event_method_feature)event_base_get_features(base);
    27         if ((f & EV_FEATURE_ET))
    28             printf("  Edge-triggered events are supported.\n");
    29         if ((f & EV_FEATURE_O1))
    30             printf("  O(1) event notification is supported.\n");
    31         if ((f & EV_FEATURE_FDS))
    32             printf("  All FD types are supported.\n");
    33         puts("");
    34     }
    35     
    36     event_base_free(base);
    37     
    38     return 0;
    39 }

    参考资料:

    1、张亮《libevent源码深度剖析系列》:http://blog.csdn.net/sparkliang/article/category/660506

    2、libevent官方文档:http://www.wangafu.net/~nickm/libevent-book/

    3、《libevent源码浅析:事件处理框架》:

      http://godorz.info/2011/02/the-annotated-libevent-sources-about-event-handling-framework/

    4、《libevent源码分析:min_heap带来的超时机制》:http://www.cppblog.com/kevinlynx/archive/2008/07/18/56511.html

  • 相关阅读:
    Linux网络编程头文件汇总
    CentOS7.6 源码安装 libxml2-2.8.0
    CentOS7.6 源码安装 glib-2.30.3
    CentOS7.6 源码安装 libevent-2.1.8-stable
    CentOS7.6 源码安装 zeromq-4.2.5
    CentOS7.6 源码安装 go1.13.12
    CentOS7.6 源码安装 openssl-1.1.1c
    CentOS7.6 源码安装 Python-3.7.4
    Go学习笔记:Linux下安装Go语言
    Go学习笔记:初识Go语言
  • 原文地址:https://www.cnblogs.com/meyao/p/libevent_notes.html
Copyright © 2020-2023  润新知