zoukankan      html  css  js  c++  java
  • libevent(九)evhttp

    用libevent构建一个http server非常方便,可参考libevent(六)http server

    主要涉及的一个结构体是evhttp:

    struct evhttp {
        /* Next vhost, if this is a vhost. */
        TAILQ_ENTRY(evhttp) next_vhost;
    
        /* All listeners for this host */
        TAILQ_HEAD(boundq, evhttp_bound_socket) sockets;
    
        TAILQ_HEAD(httpcbq, evhttp_cb) callbacks;
    
        /* All live connections on this host. */
        struct evconq connections;
    
        TAILQ_HEAD(vhostsq, evhttp) virtualhosts;
    
        TAILQ_HEAD(aliasq, evhttp_server_alias) aliases;
    
        /* NULL if this server is not a vhost */
        char *vhost_pattern;
    
        int timeout;
    
        size_t default_max_headers_size;
        ev_uint64_t default_max_body_size;
    
        /* Bitmask of all HTTP methods that we accept and pass to user
         * callbacks. */
        ev_uint16_t allowed_methods;
    
        /* Fallback callback if all the other callbacks for this connection
           don't match. */
        void (*gencb)(struct evhttp_request *req, void *);
        void *gencbarg;
    
        struct event_base *base;
    };

    值得关注的有两个成员:
      callbacks,一个链表,存放用户定义的回调函数
      connections,一个链表,存放所有连接,每个连接对应一个evhttp_connection

    evhttp_connection结构如下:

    /* A client or server connection. */
    struct evhttp_connection {
        /* we use this tailq only if this connection was created for an http
         * server */
        TAILQ_ENTRY(evhttp_connection) next;
    
        evutil_socket_t fd;
        struct bufferevent *bufev;
    
        struct event retry_ev;        /* for retrying connects */
    
        char *bind_address;        /* address to use for binding the src */
        u_short bind_port;        /* local port for binding the src */
    
        char *address;            /* address to connect to */
        u_short port;
    
        size_t max_headers_size;
        ev_uint64_t max_body_size;
    
        int flags;
    #define EVHTTP_CON_INCOMING    0x0001    /* only one request on it ever */
    #define EVHTTP_CON_OUTGOING    0x0002  /* multiple requests possible */
    #define EVHTTP_CON_CLOSEDETECT  0x0004  /* detecting if persistent close */
    
        int timeout;            /* timeout in seconds for events */
        int retry_cnt;            /* retry count */
        int retry_max;            /* maximum number of retries */
    
        enum evhttp_connection_state state;
    
        /* for server connections, the http server they are connected with */
        struct evhttp *http_server;
    
        TAILQ_HEAD(evcon_requestq, evhttp_request) requests;
    
        void (*cb)(struct evhttp_connection *, void *);
        void *cb_arg;
    
        void (*closecb)(struct evhttp_connection *, void *);
        void *closecb_arg;
    
        struct deferred_cb read_more_deferred_cb;
    
        struct event_base *base;
        struct evdns_base *dns_base;
    };

    值得关注的成员有两个:
      bufev,对应一个bufferevent
      requests,一个链表,存放该连接上的所有请求,每个请求对应evhttp_request

    evhttp_request结构如下:

    struct evhttp_request {
    #if defined(TAILQ_ENTRY)
        TAILQ_ENTRY(evhttp_request) next;
    #else
    struct {
        struct evhttp_request *tqe_next;
        struct evhttp_request **tqe_prev;
    }       next;
    #endif
    
        /* the connection object that this request belongs to */
        struct evhttp_connection *evcon;
        int flags;
    /** The request obj owns the evhttp connection and needs to free it */
    #define EVHTTP_REQ_OWN_CONNECTION    0x0001
    /** Request was made via a proxy */
    #define EVHTTP_PROXY_REQUEST        0x0002
    /** The request object is owned by the user; the user must free it */
    #define EVHTTP_USER_OWNED        0x0004
    /** The request will be used again upstack; freeing must be deferred */
    #define EVHTTP_REQ_DEFER_FREE        0x0008
    /** The request should be freed upstack */
    #define EVHTTP_REQ_NEEDS_FREE        0x0010
    
        struct evkeyvalq *input_headers;
        struct evkeyvalq *output_headers;
    
        /* address of the remote host and the port connection came from */
        char *remote_host;
        ev_uint16_t remote_port;
    
        /* cache of the hostname for evhttp_request_get_host */
        char *host_cache;
    
        enum evhttp_request_kind kind;
        enum evhttp_cmd_type type;
    
        size_t headers_size;
        size_t body_size;
    
        char *uri;            /* uri after HTTP request was parsed */
        struct evhttp_uri *uri_elems;    /* uri elements */
    
        char major;            /* HTTP Major number */
        char minor;            /* HTTP Minor number */
    
        int response_code;        /* HTTP Response code */
        char *response_code_line;    /* Readable response */
    
        struct evbuffer *input_buffer;    /* read data */
        ev_int64_t ntoread;
        unsigned chunked:1,        /* a chunked request */
            userdone:1;            /* the user has sent all data */
    
        struct evbuffer *output_buffer;    /* outgoing post or data */
    
        /* Callback */
        void (*cb)(struct evhttp_request *, void *);
        void *cb_arg;
    
        /*
         * Chunked data callback - call for each completed chunk if
         * specified.  If not specified, all the data is delivered via
         * the regular callback.
         */
        void (*chunk_cb)(struct evhttp_request *, void *);
    }; 

    值得注意的是:
      每个请求有自己的输入缓冲input_buffer、输出缓冲output_buffer。


    总结一下evhttp:
      1. 一个evhttp使用一个链表存放多个evhttp_connection,每个evhttp_connection使用链表存放多个evhttp_request。
      2. 每个evhttp_connection包含一个bufferevent,每个evhttp_request包含两个evbuffer,用于输入输出缓冲。

    说了半天,好像没看见同步机制,可见evhttp不适合多线程。

    参考资料:

    libevent源码浅析: http库

  • 相关阅读:
    Spring Boot 学习(一) 快速搭建SpringBoot 项目
    @RunWith和 SpringJUnit4ClassRunner ---->junit4和Spring一起使用
    Spring Boot的SpringApplication类详解
    @SpringBootApplication的使用
    使用阿里云搭建个人博客
    @Controller和@RestController的区别?
    蚂蚁金服开发文档中心
    Logger.getLogger()和LogFactory.getLog()的区别
    SimpleDateFormat使用详解
    SpringBoot整合RabbitMQ实现微服务间的异步消息沟通
  • 原文地址:https://www.cnblogs.com/gattaca/p/6888838.html
Copyright © 2011-2022 走看看