GNU libmicrohttpd
是一款专为嵌入式系统设计的轻量级HTTP服务器C语言库,它遵循HTTP 1.1协议标准。该库的一个显著特点是能够同时监听多个端口,提高了服务器的灵活性与扩展性。为了帮助开发者快速掌握使用方法,本文提供了简单的代码示例,旨在帮助读者更好地理解如何利用libmicrohttpd
库构建HTTP服务器并发挥其基本功能。
libmicrohttpd
, HTTP 1.1, C语言, 嵌入式系统, 代码示例
libmicrohttpd
是 GNU 项目下的一个开源库,专为嵌入式系统设计,用于创建轻量级的 HTTP 服务器。该库采用 C 语言编写,易于移植且性能高效,特别适合资源受限的环境。libmicrohttpd
遵循 HTTP 1.1 协议标准,这意味着它可以处理现代 Web 应用程序所需的复杂请求和响应。
libmicrohttpd
的设计目标之一是保持体积小巧,使其能够在内存有限的设备上运行。libmicrohttpd
可以轻松地与其他 C 或 C++ 项目集成。libmicrohttpd
提供 Web 接口,便于远程控制和监控。libmicrohttpd
提供了一个轻便的选择。HTTP (Hypertext Transfer Protocol) 是互联网上应用最为广泛的一种网络协议,用于从 Web 服务器传输超文本到本地浏览器的传输协议。HTTP 1.1 是 HTTP 协议的最新版本之一,自 1997 年发布以来,已经成为 Web 开发的标准。
libmicrohttpd
在实现 HTTP 1.1 协议时,特别注重了上述特性的支持,确保了与现代 Web 客户端的良好兼容性。此外,它还提供了一系列 API 函数,方便开发者根据具体需求定制服务器行为。例如,通过设置回调函数来处理特定类型的请求,或者配置服务器以支持 SSL 加密通信等。
嵌入式系统通常面临着资源限制的问题,如有限的内存、存储空间以及计算能力。这些限制对软件开发提出了更高的要求,特别是在网络通信方面。传统的Web服务器软件往往过于庞大,无法适应这类系统的特殊需求。因此,在嵌入式环境中部署HTTP服务器时,必须考虑以下几个关键挑战:
libmicrohttpd
通过一系列精心设计的功能和优化措施,有效地解决了上述挑战:
libmicrohttpd
的核心设计原则之一就是保持体积小巧,这使得它能够在资源极其有限的环境下运行。例如,它通过高效的内存管理和精简的代码结构,确保即使在低配置的硬件上也能流畅运行。libmicrohttpd
可以轻松地与其他C或C++项目集成。此外,其详细的文档和丰富的示例代码大大降低了学习曲线,使得开发者能够快速上手并进行维护。通过这些策略,libmicrohttpd
成为了嵌入式系统中构建HTTP服务器的理想选择,不仅满足了资源受限环境下的需求,同时也保证了高性能和高安全性。
要开始使用 libmicrohttpd
,首先需要从官方网站或通过包管理器获取该库。对于大多数 Linux 发行版,可以通过包管理器直接安装。例如,在基于 Debian 的系统上,可以使用以下命令安装:
sudo apt-get install libmicrohttpd-dev
如果需要从源码编译,可以从 GNU 官方网站下载最新版本的源码包,然后按照以下步骤进行编译和安装:
wget https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-0.9.55.tar.gz
tar -xzf libmicrohttpd-0.9.55.tar.gz
cd libmicrohttpd-0.9.55
./configure
make
sudo make install
安装完成后,接下来需要配置 libmicrohttpd
。配置主要包括设置监听端口、定义请求处理函数等。以下是一个简单的配置示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <microhttpd.h>
int handle_request(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)
{
// 处理请求的示例代码
// ...
return MHD_YES;
}
int main(int argc, char *argv[])
{
struct MHD_Daemon *daemon;
daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, 8080,
NULL, NULL, &handle_request, NULL,
MHD_OPTION_END);
if (daemon == NULL)
{
fprintf(stderr, "Failed to start daemon\n");
return 1;
}
while (1)
{
// 主循环
// ...
}
MHD_stop_daemon(daemon);
return 0;
}
在这个示例中,我们定义了一个 handle_request
函数来处理所有传入的 HTTP 请求。该函数接收请求的详细信息,并返回一个响应。主函数 main
中启动了一个监听 8080 端口的 HTTP 服务器。
libmicrohttpd
还提供了许多高级功能,例如支持 HTTPS、文件上传、多线程处理等。这些功能可以通过调用相应的 API 来启用。例如,要启用 HTTPS 支持,可以在启动服务器时添加以下选项:
MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, 8443,
NULL, NULL, &handle_request, NULL,
MHD_OPTION_HTTPS_MEM_KEY, "server.key",
MHD_OPTION_HTTPS_MEM_CERT, "server.crt",
MHD_OPTION_END);
这里假设你已经有了私钥文件 server.key
和证书文件 server.crt
。
为了能够顺利开发基于 libmicrohttpd
的项目,你需要准备一个合适的开发环境。这通常包括安装必要的工具和库,例如编译器、调试器等。
创建一个新的项目文件夹,并在其中编写你的第一个 libmicrohttpd
项目。以下是一个简单的项目结构示例:
my_http_server/
|-- src/
| |-- main.c
|-- include/
| |-- my_http_server.h
|-- Makefile
main
函数和请求处理函数。一旦项目准备好,就可以使用 Makefile 来构建你的程序。Makefile 可能看起来像这样:
CC=gcc
CFLAGS=-Wall -Wextra -std=c99 -I/usr/include/microhttpd
LDFLAGS=-lm -lpthread -lmicrohttpd
all: server
server: src/main.o
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
clean:
rm -f *.o server
使用 make
命令来编译项目,然后运行生成的可执行文件进行测试。确保服务器能够正常启动,并且能够正确处理 HTTP 请求。
通过以上步骤,你可以成功地安装和配置 libmicrohttpd
,并搭建起一个基本的开发环境。接下来,就可以开始探索更多的功能,并构建更复杂的 HTTP 服务器应用程序了。
为了帮助开发者更好地理解如何使用 libmicrohttpd
构建 HTTP 服务器,下面提供了一个基础的代码结构示例。这个示例展示了如何初始化服务器、处理 HTTP 请求以及如何停止服务器。通过这个示例,读者可以快速上手并开始构建自己的 HTTP 服务器。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <microhttpd.h>
// 定义一个处理请求的函数
int handle_request(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)
{
// 创建响应头
struct MHD_Response *response;
// 根据请求的方法来处理请求
if (strcmp(method, "GET") == 0)
{
// 对于 GET 请求,返回一个简单的 HTML 页面
response = MHD_create_response_from_buffer(strlen("<html><body>Hello, World!</body></html>"),
(void *)"<html><body>Hello, World!</body></html>",
MHD_RESPMEM_MUST_COPY);
}
else
{
// 对于其他方法,返回一个 405 方法不允许的状态码
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
MHD_add_response_header(response, "Allow", "GET");
}
// 设置响应的状态码
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
// 清理资源
MHD_destroy_response(response);
return ret;
}
int main(int argc, char *argv[])
{
struct MHD_Daemon *daemon;
// 启动一个监听 8080 端口的 HTTP 服务器
daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, 8080,
NULL, NULL, &handle_request, NULL,
MHD_OPTION_END);
if (daemon == NULL)
{
fprintf(stderr, "Failed to start daemon\n");
return 1;
}
// 主循环,等待信号或中断
while (1)
{
// 可以在这里添加其他任务,比如定时任务
}
// 停止服务器
MHD_stop_daemon(daemon);
return 0;
}
在这个示例中,我们定义了一个 handle_request
函数来处理所有传入的 HTTP 请求。该函数接收请求的详细信息,并返回一个响应。主函数 main
中启动了一个监听 8080 端口的 HTTP 服务器。当接收到 GET 请求时,服务器会返回一个简单的 HTML 页面;对于其他方法,则返回一个 405 方法不允许的状态码。
libmicrohttpd
的一大特色是支持同时监听多个端口,这为开发者提供了极大的灵活性。下面的示例展示了如何配置服务器以监听两个端口:8080 和 8081。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <microhttpd.h>
// 定义一个处理请求的函数
int handle_request(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)
{
// 创建响应头
struct MHD_Response *response;
// 根据请求的方法来处理请求
if (strcmp(method, "GET") == 0)
{
// 对于 GET 请求,返回一个简单的 HTML 页面
response = MHD_create_response_from_buffer(strlen("<html><body>Hello, World!</body></html>"),
(void *)"<html><body>Hello, World!</body></html>",
MHD_RESPMEM_MUST_COPY);
}
else
{
// 对于其他方法,返回一个 405 方法不允许的状态码
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
MHD_add_response_header(response, "Allow", "GET");
}
// 设置响应的状态码
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
// 清理资源
MHD_destroy_response(response);
return ret;
}
int main(int argc, char *argv[])
{
struct MHD_Daemon *daemon;
// 启动一个监听 8080 和 8081 端口的 HTTP 服务器
daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, 8080,
NULL, NULL, &handle_request, NULL,
MHD_OPTION_LISTENING_PORT, 8081,
MHD_OPTION_END);
if (daemon == NULL)
{
fprintf(stderr, "Failed to start daemon\n");
return 1;
}
// 主循环,等待信号或中断
while (1)
{
// 可以在这里添加其他任务,比如定时任务
}
// 停止服务器
MHD_stop_daemon(daemon);
return 0;
}
在这个示例中,我们通过向 MHD_start_daemon
函数传递额外的参数 MHD_OPTION_LISTENING_PORT
和端口号 8081,实现了同时监听两个端口的功能。这样,服务器就能够同时处理来自这两个端口的请求,提高了服务器的灵活性和扩展性。
在构建基于 libmicrohttpd
的 HTTP 服务器时,处理 HTTP 请求是至关重要的一步。请求处理涉及到解析客户端发送过来的信息,并根据这些信息生成适当的响应。下面我们将详细介绍如何在 libmicrohttpd
中实现这一过程。
libmicrohttpd
提供了一套完善的 API 来帮助开发者解析 HTTP 请求。当服务器接收到一个请求时,MHD_start_daemon
函数会调用预先定义好的请求处理函数(如前面示例中的 handle_request
)。在这个函数内部,开发者可以根据传入的参数来解析请求的具体内容。
url
参数可以获取请求的目标 URL。method
参数指明了请求的方法(如 GET、POST 等)。version
参数提供了 HTTP 版本信息。upload_data
和 upload_data_size
参数来访问这些数据。下面是一个具体的请求处理示例,展示了如何根据不同的请求方法来生成响应:
int handle_request(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)
{
// 创建响应头
struct MHD_Response *response;
// 根据请求的方法来处理请求
if (strcmp(method, "GET") == 0)
{
// 对于 GET 请求,返回一个简单的 HTML 页面
response = MHD_create_response_from_buffer(strlen("<html><body>Hello, World!</body></html>"),
(void *)"<html><body>Hello, World!</body></html>",
MHD_RESPMEM_MUST_COPY);
}
else if (strcmp(method, "POST") == 0)
{
// 对于 POST 请求,可以处理上传的数据
if (*upload_data_size > 0)
{
printf("Received POST data: %.*s\n", (int)*upload_data_size, upload_data);
}
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
}
else
{
// 对于其他方法,返回一个 405 方法不允许的状态码
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
MHD_add_response_header(response, "Allow", "GET, POST");
}
// 设置响应的状态码
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
// 清理资源
MHD_destroy_response(response);
return ret;
}
在这个示例中,我们增加了对 POST 请求的支持。当接收到 POST 请求时,服务器会打印上传的数据,并返回一个空的响应。对于其他方法,则返回一个 405 方法不允许的状态码,并在响应头中列出允许的方法。
响应生成是 HTTP 服务器的核心功能之一。正确的响应不仅可以提升用户体验,还能确保与客户端之间的交互顺畅进行。下面我们将介绍如何使用 libmicrohttpd
来生成各种类型的响应。
HTTP 响应代码用于指示请求的结果。常见的响应代码包括:
下面是一个具体的响应生成示例,展示了如何根据不同的情况生成不同类型的响应:
int handle_request(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)
{
// 创建响应头
struct MHD_Response *response;
// 根据请求的方法来处理请求
if (strcmp(method, "GET") == 0)
{
// 对于 GET 请求,返回一个简单的 HTML 页面
response = MHD_create_response_from_buffer(strlen("<html><body>Hello, World!</body></html>"),
(void *)"<html><body>Hello, World!</body></html>",
MHD_RESPMEM_MUST_COPY);
}
else if (strcmp(method, "POST") == 0)
{
// 对于 POST 请求,可以处理上传的数据
if (*upload_data_size > 0)
{
printf("Received POST data: %.*s\n", (int)*upload_data_size, upload_data);
}
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
}
else
{
// 对于其他方法,返回一个 405 方法不允许的状态码
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
MHD_add_response_header(response, "Allow", "GET, POST");
}
// 设置响应的状态码
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
// 清理资源
MHD_destroy_response(response);
return ret;
}
在这个示例中,我们根据请求的方法来决定响应的状态码。对于 GET 请求,返回 200 OK;对于 POST 请求,同样返回 200 OK;而对于其他方法,则返回 405 方法不允许的状态码。
通过上述示例,我们可以看到 libmicrohttpd
提供了灵活的方式来处理 HTTP 请求和生成响应。开发者可以根据实际需求来定制这些功能,从而构建出符合特定应用场景的 HTTP 服务器。
libmicrohttpd
不仅提供了基本的 HTTP 服务器功能,还包含了一系列高级特性,以满足更复杂的应用需求。这些特性包括但不限于支持 HTTPS、文件上传、多线程处理等。下面将详细介绍这些高级功能及其应用场景。
在现代 Web 开发中,HTTPS 已经成为了标配,因为它能够提供加密的数据传输,保障用户数据的安全。libmicrohttpd
内置了对 HTTPS 的支持,使得开发者能够轻松地为服务器添加 SSL/TLS 加密功能。
要在 libmicrohttpd
中启用 HTTPS,只需在启动服务器时添加相应的 SSL/TLS 选项即可。以下是一个简单的示例:
struct MHD_Daemon *daemon;
daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, 8443,
NULL, NULL, &handle_request, NULL,
MHD_OPTION_HTTPS_MEM_KEY, "server.key",
MHD_OPTION_HTTPS_MEM_CERT, "server.crt",
MHD_OPTION_END);
if (daemon == NULL)
{
fprintf(stderr, "Failed to start daemon\n");
return 1;
}
在这个示例中,服务器监听 8443 端口,并使用 server.crt
作为证书文件,server.key
作为私钥文件。这些文件通常由证书颁发机构签发,或者可以自行生成用于测试目的。
文件上传是 Web 应用中常见的功能之一,libmicrohttpd
也提供了相应的支持。通过设置特定的回调函数,开发者可以轻松地处理上传的文件。
下面是一个处理文件上传的基本示例:
int handle_upload(void *cls, struct MHD_Connection *connection,
const char *upload_data, size_t *upload_data_size,
size_t offset, uint8_t *to_free)
{
// 处理上传的数据
// ...
return MHD_YES;
}
int handle_request(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)
{
// 创建响应头
struct MHD_Response *response;
if (strcmp(method, "POST") == 0)
{
// 对于 POST 请求,可以处理上传的数据
if (*upload_data_size > 0)
{
printf("Received POST data: %.*s\n", (int)*upload_data_size, upload_data);
// 添加文件上传处理函数
MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, handle_upload, NULL);
}
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
}
else
{
// 对于其他方法,返回一个 405 方法不允许的状态码
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
MHD_add_response_header(response, "Allow", "POST");
}
// 设置响应的状态码
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
// 清理资源
MHD_destroy_response(response);
return ret;
}
在这个示例中,我们定义了一个 handle_upload
函数来处理上传的数据,并在 handle_request
函数中调用了 MHD_get_connection_values
来获取上传的数据。
除了上述特性外,libmicrohttpd
还支持多种其他高级功能,例如:
MHD_USE_THREAD_PER_CONNECTION
,可以让每个连接在一个单独的线程中处理,从而提高并发处理能力。在处理高并发请求时,单线程模型可能会成为瓶颈。为了提高服务器的吞吐量和响应速度,libmicrohttpd
提供了多线程处理和支持异步操作的能力。
通过启用 MHD_USE_THREAD_PER_CONNECTION
选项,libmicrohttpd
可以为每个连接分配一个独立的线程。这种方式可以充分利用多核处理器的优势,提高服务器的并发处理能力。
下面是一个启用多线程处理的示例:
struct MHD_Daemon *daemon;
daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION, 8080,
NULL, NULL, &handle_request, NULL,
MHD_OPTION_END);
if (daemon == NULL)
{
fprintf(stderr, "Failed to start daemon\n");
return 1;
}
在这个示例中,我们通过添加 MHD_USE_THREAD_PER_CONNECTION
选项启用了多线程处理模式。
除了多线程之外,libmicrohttpd
还支持异步处理模式。这种方式下,服务器不会阻塞等待 I/O 操作完成,而是继续处理其他请求,直到 I/O 操作完成后再进行后续处理。这种方式特别适用于 I/O 密集型的应用场景。
下面是一个简单的异步处理示例:
int handle_request(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)
{
// 创建响应头
struct MHD_Response *response;
// 异步处理示例
if (strcmp(method, "GET") == 0)
{
// 对于 GET 请求,异步处理数据
// ...
// 返回一个占位符响应
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
}
else
{
// 对于其他方法,返回一个 405 方法不允许的状态码
response = MHD_create_response_from_buffer(0, NULL, MHD_RESPMEM_PERSISTENT);
MHD_add_response_header(response, "Allow", "GET");
}
// 设置响应的状态码
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
// 清理资源
MHD_destroy_response(response);
return ret;
}
在这个示例中,我们为 GET 请求定义了一个异步处理流程。实际的异步处理逻辑需要根据具体的应用场景来实现。
通过上述高级特性和多线程/异步处理的支持,libmicrohttpd
能够满足开发者在构建高性能 HTTP 服务器时的各种需求。无论是需要加密的数据传输、文件上传功能还是高并发处理能力,libmicrohttpd
都能够提供相应的解决方案。
在构建基于 libmicrohttpd
的 HTTP 服务器时,性能优化是确保服务器能够高效运行的关键因素之一。以下是一些实用的性能优化建议:
libmicrohttpd
支持多线程处理,通过启用 MHD_USE_THREAD_PER_CONNECTION
选项,可以让每个连接在一个单独的线程中处理。这种方式可以充分利用多核处理器的优势,提高服务器的并发处理能力。
通过支持 GZIP 压缩,可以减轻带宽压力,提高传输效率。启用压缩后,服务器能够自动检测客户端是否支持压缩,并相应地压缩响应数据。
由于 libmicrohttpd
专为嵌入式系统设计,因此在内存管理方面需要格外注意。合理规划内存分配和释放,避免内存泄漏,可以显著提高服务器的稳定性。
在处理 I/O 密集型任务时,使用非阻塞 I/O 可以避免服务器因等待 I/O 操作而阻塞,从而提高整体性能。
合理设置连接超时和读取超时值,可以避免长时间等待无响应的连接,减少资源浪费。
对于静态资源,可以利用缓存机制减少不必要的数据传输。例如,通过设置响应头中的 Cache-Control
字段,告知客户端可以缓存响应数据。
在开发过程中,调试和错误处理是必不可少的环节。以下是一些建议,帮助开发者更好地调试和处理 libmicrohttpd
中可能出现的问题:
通过设置回调函数,可以自定义服务器的日志记录方式。这有助于追踪问题和调试,特别是在生产环境中。
对于客户端发送的错误请求,服务器应该返回适当的 HTTP 状态码,并提供有用的错误信息。例如,对于 404 Not Found 错误,可以返回一个友好的页面,告诉用户所请求的资源不存在。
在处理请求的过程中,可能会遇到各种异常情况。例如,文件读取失败、内存分配不足等。通过适当的异常处理机制,可以确保服务器在遇到这些问题时能够优雅地处理,而不是崩溃。
利用调试工具(如 GDB)可以帮助开发者更深入地了解程序的运行状态,定位问题所在。此外,还可以使用性能分析工具(如 Valgrind)来检查内存泄漏等问题。
通过实施上述性能优化建议和调试策略,开发者可以构建出更加健壮、高效的 HTTP 服务器。无论是在资源受限的嵌入式系统中,还是在处理高并发请求的场景下,libmicrohttpd
都能够提供强大的支持。
通过本文的介绍,我们深入了解了 libmicrohttpd
这款专为嵌入式系统设计的轻量级 HTTP 服务器 C 语言库。它遵循 HTTP 1.1 协议标准,并具备同时监听多个端口的能力,极大地提升了服务器的灵活性和扩展性。本文不仅详细阐述了 libmicrohttpd
的主要特点和使用场景,还提供了从安装配置到构建 HTTP 服务器的全过程指导,包括代码示例。
我们探讨了如何在资源受限的环境中部署 HTTP 服务器所面临的挑战,并介绍了 libmicrohttpd
如何通过轻量化设计、安全性增强、易于集成与维护以及高度可配置性等策略来解决这些问题。此外,还展示了如何处理 HTTP 请求与响应,以及如何利用 libmicrohttpd
的高级特性,如 HTTPS 支持、文件上传、多线程处理等,来构建功能更加强大的 HTTP 服务器。
最后,我们还讨论了性能优化建议和调试策略,帮助开发者构建出更加健壮、高效的 HTTP 服务器。无论是在资源受限的嵌入式系统中,还是在处理高并发请求的场景下,libmicrohttpd
都能够提供强大的支持。希望本文能够帮助开发者快速上手并充分发挥 libmicrohttpd
的潜力。