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 功能强大,有很多可以值的学习的地方。