CentOS7 云服务器上安装 Libmicrohttpd 库

发布时间 2023-12-03 17:56:01作者: 路有所思

本周 web 课的课程作业是实现一个类似 top 命令的网络服务,用于监控远程服务器的进程,其中使用的 web 服务器是 Libmicrohttpd,于是在此记录下我的下载安装流程,如有错误,欢迎指正!

1. Libmicrohttpd

Libmicrohttpd 是一个小型的 C 语言库,用于嵌入 HTTP 服务器功能到应用程序中。

它支持 HTTP 1.1,可在 Unix-like 系统(如 Linux)和 Windows 上运行,它还提供简单的编程接口,用于监听网络连接、解析 HTTP 请求和发送响应。

以下是在 CentOS 7 上下载、配置、编译并安装 Libmicrohttpd 的详细步骤:

2. 准备工作

  • 安装依赖工具和库:确保系统具有编译源代码所需的基本工具和库,可以通过以下命令安装:
sudo yum groupinstall "Development Tools"
sudo yum install libtool libgcrypt-devel gnutls-devel

Development Tools:是一组工具,包括编译器、链接器、调试器等,它们是编译和构建软件的基础。(比如 gcc,make 等)

Libtool:是一个用于创建可移植库的脚本,与在不同系统上创建共享库(动态链接库)相关

Libgcrypt-devel:是 Libgcrypt 的开发文件(头文件和库),用于提供加密功能

Gnutls-devel:是 GnuTLS(一个安全通信库)的开发版本,它提供了网络通信中的加密和安全功能,例如支持 HTTPS

3. 下载和解压

  • 下载 Libmicrohttpd 源代码
wget https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-latest.tar.gz
  • 解压源代码包:使用 tar 命令解压下载的文件
tar -xzvf libmicrohttpd-latest.tar.gz

4. 编译和安装

  • 配置构建环境:进入解压后的目录,并配置构建环境

可以使用 ./configure 命令来配置 Libmicrohttpd,如

  • --prefix=PATH:指定软件安装的目录,默认通常是安装到 /usr/local 目录下
  • --enable-或-disable-OPTION:启用或禁用特定的功能或选项,例如:./configure --enable-https=yes 可以开启 HTTPS 支持
cd libmicrohttpd-0.9.77
./configure --prefix=/usr/local

  • 编译源代码
make
  • 安装库:安装编译好的库到系统中
sudo make install

5. 验证安装

  • 验证安装:验证 Libmicrohttpd 是否正确安装
pkg-config --libs --cflags libmicrohttpd

如果安装正确,这个命令会输出库的版本和编译选项

如果和我一样输出的不太对,也就是类似下面这样:Package libmicrohttpd was not found in the pkg-config search path. Perhaps you should add the directory containing libmicrohttpd.pc' to the PKG_CONFIG_PATH environment variable No package 'libmicrohttpd' found

那就接着配置下面的环境变量

6. 设置环境变量

  • 设置 PKG_CONFIG_PATH 环境变量:执行以下命令将 /usr/local/lib/pkgconfig 添加到 PKG_CONFIG_PATH 环境变量中
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
  • 验证设置:再次运行 pkg-config 命令来检查 Libmicrohttpd 是否能被正确识别:
pkg-config --libs --cflags libmicrohttpd

如果一切顺利,这次命令应该能输出 Libmicrohttpd 的链接和编译选项,然后我们就将环境变量永久添加到配置文件中

  • 永久添加环境变量:为了确保这个环境变量在每次登录或开机时都被自动设置,需要将这个 export 命令添加到 shell 配置文件中,如 ~/.bashrc
    • 执行以下命令编辑 .bashrc 文件:
echo 'export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH' >> ~/.bashrc
  • 使更改生效:为了使 .bashrc 中的更改立即生效,执行以下命令:
source ~/.bashrc

7. 运行测试代码

  • 先编写一个简单的小demo,用于获取系统top命令的输出并生成HTML页面返回响应
#include <microhttpd.h>  // 引入Libmicrohttpd库
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#define PORT 8888

// 处理每个连接请求的函数
static int answer_to_connection (void *cls, struct MHD_Connection *connection, 
                                 const char *url, const char *method, 
                                 const char *version, const char *upload_data,
                                 size_t *upload_data_size, void **con_cls) {
    char *page;  // 存储生成的HTML页面内容
    FILE *fp;    // 文件指针,用于执行命令
    char path[1035];  // 存储命令输出的缓冲区

    // 执行系统命令top,以批处理模式运行一次
    fp = popen("top -b -n 1", "r");
    if (fp == NULL) {
        printf("Failed to run command\n");
        exit(1);
    }

    // 动态分配空间来存储HTML页面内容
    size_t page_size = 10000;
    page = malloc(page_size);
    if (!page) {
        perror("Malloc failed");
        exit(1);
    }

    strcpy(page, "<html><head><meta charset=\"UTF-8\"></head><body>");

    // 读取命令输出并添加到HTML页面
    while (fgets(path, sizeof(path)-1, fp) != NULL) {
        // 检查是否需要扩展缓冲区
        if (strlen(page) + strlen(path) + 8 > page_size) {
            page_size *= 2; // 加倍页面大小
            char *new_page = realloc(page, page_size);
            if (!new_page) {
                perror("Realloc failed");
                free(page);
                exit(1);
            }
            page = new_page;
        }
        strcat(page, path);
        strcat(page, "<br>");
    }
    strcat(page, "</body></html>");

    struct MHD_Response *response;
    int ret;

    // 创建响应对象,其中包含生成的HTML页面
    response = MHD_create_response_from_buffer(strlen(page), (void *)page, MHD_RESPMEM_MUST_FREE);
    ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
    MHD_destroy_response(response);

    pclose(fp);
    return ret;
}

int main () {
    struct MHD_Daemon *daemon;  // 定义服务器守护进程

    // 启动守护进程,监听指定端口
    daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL, 
                              (MHD_AccessHandlerCallback) answer_to_connection, NULL, MHD_OPTION_END);
    if (NULL == daemon) return 1;  // 如果守护进程启动失败,返回1

    getchar();  // 等待用户输入以退出

    MHD_stop_daemon(daemon);  // 停止守护进程
    return 0;
}
  • 编译执行命令如下:
gcc test.c -o test -lmicrohttpd
./test
  • 好的,有可能还会遇到下面的报错:
error while loading shared libraries: libmicrohttpd.so.12: cannot open shared object file: No such file or directory

那就继续下面的步骤

8. 解决运行时库加载的问题

  • 设置 LD_LIBRARY_PATH 环境变量:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
  • 更新动态链接器缓存:
sudo ldconfig
  • 再次编译运行下:
gcc test.c -o test -lmicrohttpd
./test

  • 终于没有报错,此时访问下服务器地址,如:http://xxx.xxx.xxx.xxx:8888 (这里的8888端口是因为我代码里写着监听端口是8888),成功显示 top 命令的输出如下:

9. 卸载 Libmicrohttpd

如果需要卸载重试的话,可以尝试下面的命令

  • 进入之前编译 Libmicrohttpd 的目录

  • 执行卸载命令:

sudo make uninstall
  • 可选:清理环境变量配置(从 .bashrc 中删除相关行)