用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. spark sql error mismatched input 'union' expecting { <EOF>,''................................

    给union的前后sql加括号就可以解决

  2. 【java 数据结构】还不会二叉树?一篇搞定二叉树

    二叉树是我们常见的数据结构之一,在学习二叉树之前我们需要知道什么是树,什么是二叉树,本篇主要讲述了二叉树,以及二叉树的遍历. 你能get到的知识点? 1.树的介绍 2.二叉树的介绍 3.二叉树遍历的四 ...

  3. Adaptert Listview 优化

    这次是关于Listview的优化的,之前一直采用愚蠢的方式来使用listview,出现的情况就是数据多的话下拉的时候会出现卡顿的情况,内存占用多.所以学习了关于listview的优化,并且这也是普遍使 ...

  4. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十四)之Type Information

    Runtime type information (RTTI) allow you to discover and use type information while a program is ru ...

  5. C#——继承

    在某基类中声明 virtual 并在一个或多个派生类中被重新定义的成员函数称为虚函数. 虚函数的作用就是实现多态性(Polymorphism),多态性是将接口与实现进行分离. C#作为完全面向对象语言 ...

  6. C - Sweets Eating

    规律题 前缀和+规律 先求前缀和...答案为c[i]=arr[i]+c[i-m]//i>m时. #include<bits/stdc++.h> using namespace std ...

  7. Django系列操作

    每次用到都去百度找....找的还不行~~得自己改~~耗时耗力虽然不难~~~直接贴代码记录下方便自己用~~~~ Django之分页 定义成一个块,直接引用到对应的位置即可... <div clas ...

  8. 极验反爬虫防护分析之slide验证方式下图片的处理及滑动轨迹的生成思路

    本文要分享的内容是去年为了抢鞋而分析 极验(GeeTest)反爬虫防护的笔记,由于篇幅较长(为了多混点CB)我会按照我的分析顺序,分成如下四个主题与大家分享: 极验反爬虫防护分析之交互流程分析 极验反 ...

  9. 非oracle用户sysdba登陆出TNS-12547错误

    这个问题mark下,测试机器oracle从12c升级到19c后,非oracle用户 sysdba登陆不上.sqlnet.log里错误是: sqplus uasa/uasa error       Fa ...

  10. WPF中在Gmap.net中将Marker动起来

    前一段时间说过一篇绘制极坐标的,这段时间对它进行了改造已经今非昔比了,功能实现了很多,我目的是让Marker动起来,然后还会绘制Route,上篇也就是简单的绘制了Route,没有关于Marker的相关 ...