清单 4. 使用 libevent 服务的简单示例
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <event.h>
#include <evhttp.h>
void generic_request_handler(struct evhttp_request *req, void *arg)
{
struct evbuffer *returnbuffer = evbuffer_new();
evbuffer_add_printf(returnbuffer, "Thanks for the request!");
evhttp_send_reply(req, HTTP_OK, "Client", returnbuffer);
evbuffer_free(returnbuffer);
return;
}
int main(int argc, char **argv)
{
short http_port = 8081;
char *http_addr = "192.168.0.22";
struct evhttp *http_server = NULL;
event_init();
http_server = evhttp_start(http_addr, http_port);
evhttp_set_gencb(http_server, generic_request_handler, NULL);
fprintf(stderr, "Server started on port %dn", http_port);
event_dispatch();
return(0);
}
应该可以通过前面的示例看出代码的基本结构,不需要解释。主要元素是 evhttp_set_gencb() 函数(它设置当收到 HTTP 请求时要使用的回调函数)和 generic_request_handler() 回调函数本身(它用一个表示成功的简单消息填充响应缓冲区)。
HTTP 包装器提供许多其他功能。例如,有一个请求解析器,它会从典型的请求中提取出查询参数(就像处理 CGI 请求一样)。还可以设置在不同的请求路径中要触发的处理函数。通过设置不同的回调函数和处理函数,可以使用路径 '/db/' 提供到数据库的接口,或使用 '/memc' 提供到 memcached 的接口。
libevent 工具包的另一个特性是支持通用计时器。可以在指定的时间段之后触发事件。可以通过结合使用计时器和 HTTP 实现提供轻量的服务,从而自动地提供文件内容,在修改文件内容时更新返回的数据。例如,以前要想在新闻频发的活动期间提供即时更新服务,前端 web 应用程序就需要定期重新装载新闻稿,而现在可以轻松地提供内容。整个应用程序(和 web 服务)都在内存中,因此响应非常快。
这就是 清单 5 中的示例的主要用途:
清单 5. 使用计时器在新闻频发的活动期间提供即时更新服务
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <event.h>
#include <evhttp.h>
#define RELOAD_TIMEOUT 5
#define DEFAULT_FILE "sample.html"
char *filedata;
time_t lasttime = 0;
char filename[80];
int counter = 0;
void read_file()
{
int size = 0;
char *data;
struct stat buf;
stat(filename,&buf);
if (buf.st_mtime > lasttime)
{
if (counter++)
fprintf(stderr,"Reloading file: %s",filename);
else
fprintf(stderr,"Loading file: %s",filename);








