本周 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
中删除相关行)