基于libevent的http服务器实现

基于libevent的http服务器实现

//libevent的http服务器简单实现方式

#include
#include
#include
#include
//for struct evkeyvalq
#include
#include
#include
#include
#include
#include
#include

#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  interface to listen on, default is 0.0.0.0\n"
        "-p      port number to listen on, default is 1984\n"
        "-d           run as a deamon\n"
        "-t   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;
}

更多内容查看我的专栏 ,或个人主页

更多编程内容见公众号 xutopia77,有更多系列的libevent文章介绍

Original: https://www.cnblogs.com/xutopia/p/15811659.html
Author: xutopia
Title: 基于libevent的http服务器实现

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/612687/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Redis源码系列(一)

    Redis源码系列——内存管理 函数原型 src/zmalloc.h 函数指针与 void*指针的使用,提供了一个泛型的机制 /*stringfication*/ #define …

    Linux 2023年6月8日
    092
  • linux 命令 df -h 查不到新添加的硬盘

    云平台:腾讯云系统:ubuntu 20.04 第一部分:缘由 1、我的一台云服务器上挂载了两块硬盘。一块 50G 系统盘、一块 400G 数据盘。然后我查询目前在 Linux 系统…

    Linux 2023年5月27日
    0323
  • OpenSSL测试-随机数

    任务详情 在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务 使用OpenSSL定义一个私有函数 static int getRandom(char…

    Linux 2023年6月8日
    092
  • C++的vector的使用方法

    vector c++的vector的使用方法,创建,初始化,插入,删除等。 #include "ex_vector.h" #include #include #…

    Linux 2023年6月14日
    086
  • netstat 命令查看端口状态详解

    转载请注明出处: netstat 可以查看服务器当前端口列表及指定端口的连接状态等; -t : 指明显示TCP端口,t是TCP的首字母。 -u : 指明显示UDP端口,u是UDP的…

    Linux 2023年6月14日
    077
  • django queryset列表合并

    import itertools queryset_top = query.filter(is_top=True).order_by("-updated_at"…

    Linux 2023年6月14日
    065
  • 操作系统实现-printk

    博客网址:www.shicoder.top微信:18223081347欢迎加群聊天 :452380935 这一次我们来实现最基础,也是最常见的函数 print,大家都知道这个是可变…

    Linux 2023年6月13日
    096
  • 剪贴板被占用导致应用使用剪贴板拷贝内容失败抛出 COMException 0x800401D0 错误

    本文记录某些软件,例如 向日葵远程控制 软件占用剪贴板,导致 WPF 应用使用剪贴板拷贝内容和设置剪贴板时,抛出 System.Runtime.InteropServices.CO…

    Linux 2023年6月6日
    0127
  • Postman环境变量的使用

    前言 请注意,Postman新版有ui上的改动,本文使用的Postman 版本8.4.0 for Mac, ui有调整,但是功能无改变。 Postman是一款接口调测的软件,服务端…

    Linux 2023年6月14日
    098
  • LeetCode-443. 压缩字符串

    题目来源 题目详情 给你一个字符数组 chars ,请使用下述算法压缩: 从一个空字符串 s 开始。对于 chars 中的每组 连续重复字符 : 如果这一组长度为 1 ,则将字符追…

    Linux 2023年6月7日
    0100
  • 2021 个人年度小结

    因为不用考研,所以大四一整年可以自由自在地学习一直以来想学却又没时间去学的东西。快乐的大四时光总是显得十分短暂,这篇博客主要用来总结过去一年所学的知识。 计算机组成原理 上的是哈尔…

    Linux 2023年6月7日
    094
  • 运维自动化之ansible,轻松实现企业级自动化运维

    Original: https://www.cnblogs.com/magecxy/p/15561194.htmlAuthor: 程序员面试吧Title: 运维自动化之ansibl…

    Linux 2023年5月27日
    083
  • shell之磁盘容量检查,配合crontab可以定时清理磁盘

    我的做法: !/bin/bashAvailable=df -k | sed -n 2p | awk ‘{print $4}’if [ $Available -eq 0 ];then…

    Linux 2023年5月28日
    073
  • 正则表达式 9. 替换分组使用

    https://www.zybuluo.com/Zjmainstay/note/709093 替换分组使用 (9.1)给源串每个链接加上http://www.zjmainstay….

    Linux 2023年6月13日
    089
  • Linux 0.11源码阅读笔记-总结

    Linux 0.11主要包含文件管理和进程管理两个部分。进程管理包括内存管理、进程管理、进程间通信模块。文件管理包含磁盘文件系统,打开文件内存数据。磁盘文件系统包括空闲磁盘块管理,…

    Linux 2023年5月27日
    076
  • Identity Server 4客户端认证控制访问API(一)

    一、说明 我们将定义一个api和要访问它的客户端,客户端将在identityser上请求访问令牌,并使用访问令牌调用api 二、项目结构与准备 1、创建项目QuickStartId…

    Linux 2023年6月13日
    093
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球