用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库














最新文章

  1. Vue.js 快速入门
  2. CozyRSS开发记录-中断
  3. [转]ios push
  4. 查询数据过多页面反应慢引入缓存解决方案(Redis、H2)
  5. python学习笔记整理——元组tuple
  6. loj 1167(二分+最大流)
  7. iOS 蓝牙开发之传输图片
  8. cursorfilter
  9. (原)caffe在ubuntu中设置GPU的ID号及使用多个GPU
  10. 期末考试--nyoj-757
  11. Easyui 异步树直接所有展开
  12. 【机器学习笔记之三】CART 分类与回归树
  13. Tomcat下使用Druid配置JNDI数据源
  14. 新更新,又是一年了。这次记录下关于android版的WeiboDemo的问题
  15. 让shell脚本中的echo输出带颜色
  16. Hive 的基本概念
  17. UE4 材质Lerp节点解疑
  18. (转找了好久)实现一个2008serve的IIS的虚拟目录(通过网络路径(UNC)的形式,共享在另外一个2008服务器上
  19. 【题解】 [SCOI2011]糖果 (差分约束)
  20. Log4j中conversionPattern的含义

热门文章

  1. Struts2-学习笔记系列(8)-异常处理
  2. Lua 5.3 -- SOL2.0 用户指南 【1】
  3. Docker php安装扩展步骤详解
  4. iOS技能 - 最新美团、百度、腾讯、头条、阿里 面试题目记录
  5. 使用Scanner接受用户键盘输入的值
  6. Python递归爬取头条用户的所有文章、视频
  7. stand up meeting 12-2
  8. git分支,git commit,git流程
  9. uniqid用法
  10. 2019.11.13课堂实验之用Linux下的shell脚本完成两文本交替输出