libevent是一个事件触发的网络库,适用于windows、linux、bsd等多种平台,内部使用select、epoll、kqueue等系统调用管理事件机制。分布式缓存memcached据说也是libevent based,而且libevent在使用上可以做到跨平台,而且根据libevent官方网站上公布的数据统计,似乎也有着非凡的性能。
更多的信息可以去这里了解:http://baike.baidu.com/view/1590523.htm
先下载 libevent,官方地址是:http://monkey.org/~provos/libevent/,在下面有下载地址列表,我这里下载了1.4.10-stable这个版本。
安装 libevnet:
#wget http://monkey.org/~provos/libevent-1.4.10-stable.tar.gz #tar zxvf libevent-1.4.10-stable.tar.gz #cd libevent-1.4.10-stable #./configure #make #make install
接下来看这个 c 语言示例程序 my_xhttpd.c:
#include <sys/types.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <netinet/in.h>
#include <net/if.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <assert.h>
#include <signal.h>
#include <stdbool.h>
#include <err.h>
// 引入 libevent 头文件
#include <event.h>
#include <evhttp.h>
// 请求处理模块
void http_handler(struct evhttp_request *req, void *arg)
{
struct evbuffer *buf;
buf = evbuffer_new();
// 分析URL参数
char *decode_uri = strdup((char*) evhttp_request_uri(req));
struct evkeyvalq http_query;
evhttp_parse_query(decode_uri, &http_query);
free(decode_uri);
// 从http头中获取参数,如果是GET传输,这里就可以取得action的值
const char *request_value = evhttp_find_header(&http_query, "data");
// 返回给浏览器的信息
evhttp_add_header(req->output_headers, "Content-Type",
"text/html; charset=UTF-8");
evhttp_add_header(req->output_headers, "Server", "my_httpd");
//evhttp_add_header(req->output_headers, "Connection", "keep-alive");
evhttp_add_header(req->output_headers, "Connection", "close");
// 将要输出的值加入到输出缓存中
if(request_value != NULL) {
evbuffer_add_printf(buf, "%s", request_value);
} else {
evbuffer_add_printf(buf, "%s", "no error.");
}
// 输出内容到浏览器
evhttp_send_reply(req, HTTP_OK, "OK", buf);
// 内存释放
evhttp_clear_headers(&http_query);
evbuffer_free(buf);
}
int main(int argc, char **argv)
{
char *host_ip = "0.0.0.0";
int host_port = 8080;
int timeout = 3;
struct evhttp *httpd;
event_init();
// 绑定本机ip和端口,在访问时一定要把8080端口开放出来
httpd = evhttp_start(host_ip, host_port);
if (httpd == NULL) {
fprintf(stderr, "Error: Unable to listen on %s:%d\n\n", host_ip, host_port);
exit(1);
}
// 设置请求超时时间
evhttp_set_timeout(httpd, timeout);
// 设置请求的处理函数
evhttp_set_gencb(httpd, http_handler, NULL);
event_dispatch();
evhttp_free(httpd);
return 0;
}
编译源码:gcc -o my_httpd my_httpd.c -L/usr/local/lib/ -levent -I/usr/local/include/ -lz -lbz2 -lrt -lpthread -lm -lc -O2
编译成功后就会在当前目录生成一个 my_httpd 可执行文件。
放在后台启动:./my_httpd >/dev/null 2>&1 &
打开浏览器,输入访问地址,如图:
这只是个用来学习的简单示例,但 libevent 功能强大,有很多可以值的学习的地方。
