用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:, /* a chunked request */
userdone:; /* 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库














libevent(九)evhttp的更多相关文章

  1. libevent(十三)evhttp事件处理流程

    在libevent(六)http server中,作为一个单线程http server,不仅要监听每个连接的到来,还要监听每个连接上的I/O事件. 查看源码可知,在evhttp_bind_socket ...

  2. libevent(九)bufferevent

    bufferevent,带buffer的event struct bufferevent { struct event_base *ev_base; const struct bufferevent_ ...

  3. 编译libevent源代码(Windows)

    学习笔记,只是记录本次成功用libevent源代码进行编译.环境为MinGW+VS2008+Msys. 0.下载libevent库 http://libevent.org/ 下载stable稳定版的库 ...

  4. libevent(十)bufferevent 2

    接上文libevent(九)bufferevent 上文主要讲了bufferevent如何监听读事件,那么bufferevent如何监听写事件呢? 对于一个fd,只要它的写缓冲区没有满,就会触发写事件 ...

  5. Thrift 基础(C++ rpc )

    一.thrift简介 thrift是Facebook开源的一套rpc框架,目前被许多公司使用 我理解的特点 使用IDL语言生成多语言的实现代码,程序员只需要实现自己的业务逻辑 支持序列化和反序列化操作 ...

  6. libevhtp初探

    libevent的evhttp不适合多线程,libevhtp重新设计了libevent的http API,采用了和memcached类似的多线程模型. worker线程的管道读事件的回调函数为htp_ ...

  7. libevent源码深度剖析九

    libevent源码深度剖析九 ——集成定时器事件 张亮 现在再来详细分析libevent中I/O事件和Timer事件的集成,与Signal相比,Timer事件的集成会直观和简单很多.Libevent ...

  8. Libevent::evhttp服务器

    #include <cstdio> #include <stdio.h> #include <stdlib.h> #include <string.h> ...

  9. Libevent::evhttp服务器下载

    void http_handler_Get_Download(struct evhttp_request *req, void *arg) { if (req == NULL) { return; } ...

随机推荐

  1. Django-rest-framework 是个什么鬼?

    作者:HelloGitHub-追梦人物 我们首先来回顾一下传统的基于模板引擎的 django 开发工作流: 绑定 URL 和视图函数.当用户访问某个 URL 时,调用绑定的视图函数进行处理. 编写视图 ...

  2. Linux C++ 网络编程学习系列(4)——多路IO之epoll基础

    epoll实现多路IO 源码地址:https://github.com/whuwzp/linuxc/tree/master/epoll 源码说明: server.cpp: 监听127.1:6666,功 ...

  3. Win8.1/Win10在某些程序输入中文变成问号的解决方法

    之前我是使用Win8.1,在某些软件上输入中文,却显示问号,换输入法也没用,当时也没用太在意,后来升级到Win10还是一样.同样的软件在其它Win8.1/Win10电脑却可以正常显示中文. 解决方法如 ...

  4. Ajax 简述与基础语法

    目录 Ajax 1. 原生 JS 实现 Ajax 2. 使用 Ajax 实现异步通信 a. Ajax 的基础语法 b. 用 Ajax 传递数据 i. 传递字符串数据 ii. 传递 JSON 数据 3. ...

  5. . Number throry

    steve 学完了快速幂,现在会他快速的计算:(ij)%d , Alex 作为一个数学大师,给了 steve 一个问题:已知i∈[1,n],j∈[1,m] ,计算满足 (ij)%d=0 的 (i,j) ...

  6. 原创Hbase1.2.1集群安装

    [hadoop@Hmaster install]$ tar -zxvf hbase-1.2.1-bin.tar.gz -C ~ [hadoop@Hmaster install]$vi ~/.bash_ ...

  7. SpringCloud-Hystrix 服务降级、熔断

    Hystrix 是什么? Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时.异常等,Hystrix 能够保证在一个依赖出问题的情况下 ...

  8. iview使用之怎样通过render函数在tabs组件中添加标签

    在实际项目开发中我们通常会遇到一些比较'新颖'的需求,而这时iview库里往往没有现成可用的组件示例,所以我们就需要自己动手翻阅IviewAPI进行自定义一些组件,也可以说是将iview库里的多种组件 ...

  9. mongodb connection refused because too many open connections: 819

    Env Debian 9 # 使用通用二进制方式安装 # mongod --version db version v3.4.21-2.19 git version: 2e0631f5e0d868dd5 ...

  10. Java 虚拟机中的运行时数据区分析

    本文基于 JDK1.8 阐述分析 运行过程 我们都知道 Java 源文件通过编译器编译后,能产生相应的 .Class 文件,也就是字节码文件.而字节码文件通过 Java 虚拟机中的解释器,编译成特定机 ...