基于libevent的http服务器实现
598 字
3 分钟
基于libevent的http服务器实现
基于libevent的http服务器实现
//libevent的http服务器简单实现方式
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>//for struct evkeyvalq#include <sys/queue.h>#include <event.h>#include <event2/http.h>#include <event2/http_struct.h>#include <event2/http_compat.h>#include <event2/util.h>#include <signal.h>
#define LOG_INFO printf#define LOG_DBG printf#define LOG_ERR printf
#define MYHTTPD_SIGNATURE "httpd v 0.0.1"
//处理模块void httpd_handler(struct evhttp_request *req, void *arg) { char output[2048] = "\0"; char tmp[1024];
//获取客户端请求的URI(使用evhttp_request_uri或直接req->uri) const char *uri; uri = evhttp_request_uri(req); sprintf(tmp, "uri=%s\n", uri); strcat(output, tmp);
sprintf(tmp, "uri=%s\n", req->uri); strcat(output, tmp); //decoded uri char *decoded_uri; decoded_uri = evhttp_decode_uri(uri); sprintf(tmp, "decoded_uri=%s\n", decoded_uri); strcat(output, tmp);
//解析URI的参数(即GET方法的参数) struct evkeyvalq params; //将URL数据封装成key-value格式,q=value1, s=value2 evhttp_parse_query(decoded_uri, ¶ms); //得到q所对应的value sprintf(tmp, "q=%s\n", evhttp_find_header(¶ms, "q")); strcat(output, tmp); //得到s所对应的value sprintf(tmp, "s=%s\n", evhttp_find_header(¶ms, "s")); strcat(output, tmp);
free(decoded_uri);
//获取POST方法的数据 char *post_data = (char *) EVBUFFER_DATA(req->input_buffer); sprintf(tmp, "post_data=%s\n", post_data); strcat(output, tmp);
/* 输出到客户端 */
//HTTP header evhttp_add_header(req->output_headers, "Server", MYHTTPD_SIGNATURE); evhttp_add_header(req->output_headers, "Content-Type", "text/plain; charset=UTF-8"); evhttp_add_header(req->output_headers, "Connection", "close"); //输出的内容 struct evbuffer *buf; buf = evbuffer_new(); evbuffer_add_printf(buf, "It works!\n%s\n", output); evhttp_send_reply(req, HTTP_OK, "OK", buf); evbuffer_free(buf);
}void show_help() { char *help = "http://localhost:8080\n" "-l <ip_addr> interface to listen on, default is 0.0.0.0\n" "-p <num> port number to listen on, default is 1984\n" "-d run as a deamon\n" "-t <second> timeout for a http request, default is 120 seconds\n" "-h print this help and exit\n" "\n"; fprintf(stderr,"%s",help);}//当向进程发出SIGTERM/SIGHUP/SIGINT/SIGQUIT的时候,终止event的事件侦听循环void signal_handler(int sig) { switch (sig) { case SIGTERM: case SIGHUP: case SIGQUIT: case SIGINT: event_loopbreak(); //终止侦听event_dispatch()的事件侦听循环,执行之后的代码 break; }}
int main(int argc, char *argv[]) {
//自定义信号处理函数 signal(SIGHUP , signal_handler); signal(SIGTERM , signal_handler); signal(SIGINT , signal_handler); signal(SIGQUIT , signal_handler);
//默认参数 char *httpd_option_listen = "0.0.0.0"; int httpd_option_port = 8080; int httpd_option_daemon = 0; int httpd_option_timeout = 120; //in seconds
LOG_INFO("http server start %s:%d\n", httpd_option_listen, httpd_option_port);
//获取参数 int c; while ((c = getopt(argc, argv, "l:p:dt:h")) != -1) { switch (c) { case 'l' : httpd_option_listen = optarg; break; case 'p' : httpd_option_port = atoi(optarg); break; case 'd' : httpd_option_daemon = 1; break; case 't' : httpd_option_timeout = atoi(optarg); break; case 'h' : default : show_help(); exit(EXIT_SUCCESS); } }
//判断是否设置了-d,以daemon运行 if (httpd_option_daemon) { pid_t pid; pid = fork(); if (pid < 0) { perror("fork failed"); exit(EXIT_FAILURE); } if (pid > 0) { //生成子进程成功,退出父进程 exit(EXIT_SUCCESS); } }
/* 使用libevent创建HTTP Server */
//初始化event API event_init();
//创建一个http server struct evhttp *httpd; httpd = evhttp_start(httpd_option_listen, httpd_option_port); evhttp_set_timeout(httpd, httpd_option_timeout);
//指定generic callback evhttp_set_gencb(httpd, httpd_handler, NULL); //也可以为特定的URI指定callback //evhttp_set_cb(httpd, "/", specific_handler, NULL);
//开始事件监听,分发 event_dispatch();
//释放资源 evhttp_free(httpd); return 0;}支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!
基于libevent的http服务器实现
https://xutopia.top/blog/libevent-http-server-implementation/
