基于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)

大家都在看

  • mysql二进制安装脚本部署

    mysql二进制安装脚本部署 mysql二进制安装脚本部署 单实例 使用函数的单实例 使用函数的单实例或者多实例 单实例 [root@localhost ~]# mkdir mys…

    Linux 2023年6月6日
    0120
  • 【Leetcode】63. 不同路径 II

    一个机器人位于一个 m x n网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在…

    Linux 2023年6月6日
    097
  • 字节 字符 位(比特)

    位(bit):binary digit,计算机储存的最小单位,n个比特可以确定2^n个情况,如11010100为8位。 字节(byte):一个字节储存8位无符号数,范围为0-225…

    Linux 2023年6月13日
    0107
  • 网络安全之浅谈攻击

    最近大家也关注到了新闻,USA又对我国的一些总要的事业单位和网络基础设施进行的非法的攻击和渗透,窃取了大量的数据。可见看似和平静的水面,其实一直都是暗藏波涛,网络安全又被提摆到公众…

    Linux 2023年6月6日
    085
  • 大数据Hadoop集群的扩容及缩容(动态添加删除节点)

    添加白名单和黑名单 白名单,表示在白名单的主机IP地址可以用来存储数据 企业中;配置白名单,可以尽量防止黑客恶意访问攻击。 配置白名单步骤如下:原文:sw-code 1)在Name…

    Linux 2023年6月8日
    0134
  • jenkins

    jenkins 1.简介 1.1 SVN介绍 1.2 Maven介绍 1.3 Ant介绍 1.4 Gradle介绍 1.5 jenkins工作原理 1.6 jenkins特点 2….

    Linux 2023年6月7日
    0117
  • MySQL-配置参数时 报错:remove CMakeCache.txt and rerun cmake.On Debian/Ubuntu……

    报错:remove CMakeCache.txt and rerun cmake.On Debian/Ubuntu…… 原因: 1、第一次配置参数时,不完整…

    Linux 2023年6月13日
    0123
  • rpm简单使用

    rpm描述:利用源码包编译成rpm时,会去指定安装好这个包的位置本质:解压,然后拷贝到相关的目录,然后执行脚本 查询所有已经安装过的包 查看安装位置 解压rpm 查看脚本 查看配置…

    Linux 2023年6月7日
    077
  • MySQL架构和存储引擎、系统默认数据库介绍

    采用C/S架构,即客户端/服务器。客户端和服务器区分开,通过客户端发送请求来和服务器交互。 存储引擎:MySQL管理数据文件的一种技术。 myisam innodb myisam特…

    Linux 2023年6月7日
    0114
  • Log4j 2 日志框架

    Apache Log4j 2 是对 Log4j 的升级,它比其前身 Log4j 1.x 提供了显着改进,并提供了 Logback 中可用的许多改进,同时修复了 Logback 架构…

    Linux 2023年6月8日
    093
  • Linux虚拟机追加扩展磁盘

    一、使用VMware给虚拟机追加磁盘 使用VMware打开虚拟机设置对话框,选择硬盘,点击右侧的扩展按钮,输入扩展后的磁盘容量。 点击扩展按钮。提示磁盘已成功扩展。 二、对闲置的空…

    Linux 2023年6月6日
    0124
  • Redis高可用架构Sentinel

    1 简介 哨兵是用来解决redis高可用性的,可以监控集群中主从的变化,然后进行故障转移。一套合理的监控机制是Sentinel节点判定节点不可达的重要保证,Redis Sentin…

    Linux 2023年6月13日
    0101
  • Visual Studio使用docker开发卡 vs2017u5 exists, deleting (vsdbg的问题)

    引言在使用 Visual Studio 进行 Docker 运行调试的时候会出现无法调试的问题。出现类似一下症状:Info: Using vsdbg version ‘…

    Linux 2023年6月14日
    072
  • .NET Core 3.0, 发布将于今晚开始!

    期待已久的.NET Core 3.0即将发布! .NET Core 3.0在.NET Conf上发布。大约还有9个多小时后,.NET Conf开始启动。 第1天-9月23日 9:0…

    Linux 2023年6月7日
    088
  • Linux下如何彻底删除(卸载)MySQL?

    工具: CentOS 7 Mysql Xshell 首先连接操作系统,切换到root用户。 如果是使用yum安装的mysql,使用如下命令进行卸载(不能确定使用何种方式安装的mys…

    Linux 2023年6月8日
    098
  • Pyinstaller打包教程

    由于用户使用Python脚本的时候可能没有运行环境,所以需要打包。记录下碰到的问题。 安装 pip install –upgrade pyinstaller 安装最新开发版 pi…

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