Libevent 不仅仅是一个网络 IO 库,它还附带了一个轻量级的
HTTP 协议实现——evhttp。虽然它不如 Nginx
强大,但用于嵌入式设备、内部 API
服务或简单的文件服务器已经绰绰有余。
1. 快速上手
编写一个返回 “Hello World” 的 HTTP 服务器非常简单。
#include <event2/event.h>
#include <event2/http.h>
#include <event2/buffer.h>
// 请求处理回调
void generic_handler(struct evhttp_request *req, void *arg) {
// 1. 创建响应 buffer
struct evbuffer *buf = evbuffer_new();
if (!buf) return;
evbuffer_add_printf(buf, "Hello World! Requested: %s\n", evhttp_request_get_uri(req));
// 2. 发送响应 (HTTP 200 OK)
evhttp_send_reply(req, HTTP_OK, "OK", buf);
// 3. 清理
evbuffer_free(buf);
}
int main() {
struct event_base *base = event_base_new();
struct evhttp *http = evhttp_new(base);
// 绑定端口
if (evhttp_bind_socket(http, "0.0.0.0", 8080) != 0) {
fprintf(stderr, "Bind failed\n");
return 1;
}
// 设置通用回调 (处理所有未匹配特定 URI 的请求)
evhttp_set_gencb(http, generic_handler, NULL);
event_base_dispatch(base);
evhttp_free(http);
event_base_free(base);
return 0;
}2. 核心功能
2.1. 路由分发
除了
evhttp_set_gencb,你还可以为特定路径设置回调:
evhttp_set_cb(http, "/images", image_handler, NULL);
evhttp_set_cb(http, "/api/login", login_handler, NULL);2.2. 解析参数
evhttp 提供了简单的 URI 解析功能:
const char *uri = evhttp_request_get_uri(req);
struct evhttp_uri *decoded = evhttp_uri_parse(uri);
const char *query = evhttp_uri_get_query(decoded);
// ... 解析 query string ...2.3. 处理 POST Body
struct evbuffer *in_buf = evhttp_request_get_input_buffer(req);
size_t len = evbuffer_get_length(in_buf);
// 读取数据...3. 局限性
虽然 evhttp
很好用,但在生产环境中使用需注意: 1. 仅支持
HTTP/1.1: 不支持 HTTP/2 或 HTTP/3。 2.
单线程: 默认情况下,evhttp
依附于创建它的
event_base。如果需要多线程处理,需要自己创建多个
event_base 和 evhttp 实例,并利用
SO_REUSEPORT 绑定同一端口。 3.
功能缺失: 没有原生的 WebSocket
支持,没有完善的 Keep-Alive
超时管理(需要自己加定时器)。
完整代码: 02-http-server.c
4. 总结
evhttp 是 Libevent
赠送的一个实用工具。对于不需要复杂 Web 特性的 C/C++
后端服务,它是最快的实现路径。但如果你的需求涉及
HTTP/2、WebSocket 或极高的并发,建议集成
nghttp2 或使用专业的 Web 服务器。
上一篇: 04-architecture/business-integration.md - 业务集成模式 下一篇: 05-protocols/evdns.md - 异步 DNS 解析