1.GNU Libmicrohttpd是一个用来在项目中内嵌http服务器的C语言库。
2.特点
(1)C语言库,小而快。
(2)API非常简单,且都是可重入的。
(3)兼容HTTP1.1。
(4)支持4种多线程模型(select、poll、pthread、thread poll)。
(5)跨平台。
(6)生成的二制文件只有32K(不包含TLS/SSL等额外功能)。
3.编译调用
将其添加进项目中,生成一个头文件和一个静态库文件。调用时需要引用头文件和库文件两个文件。
4.main函数
main函数核心调用只有2个函数:MHD_start_daemon,MHD_stop_daemon,分别开始和停止http服务器。
int main()
{
const int port = 8888;
struct MHD_Daemon* daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, port , NULL, NULL,
connectionHandler, NULL, MHD_OPTION_END);
if (daemon == NULL) {
std::cout << "cannot start server!\n";
return -1;
}
std::cin.get();
MHD_stop_daemon(daemon);
return 0;
}
MHD_start_daemon函数包含非常多的参数,这也意味着它集成了很多的功能,这里只关注四个参数,其它都为NULL:
(1)MHD_USE_INTERNAL_POLLING_THREAD。这个参数与其他两个参数(MHD_USE_POLL_INTERNAL_THREAD、MHD_USE_EPOLL_INTERNAL_THREAD)一起构成了microhttpd支持的三种模式:select、poll、epoll。用户必须选择其中之一。具体信息见源码。
(2)port。端口号。
(3)connectHandler。处理请求的函数。
(4)MHD_OPTION_END。由于MHD_start_daemon最后一个参数是一个变参,因此MHD_OPTION_END用来表示变参终止。
5.connectionHandler回调函数
int connectionHandler( 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)
{
const char* pageBuffer = "<html><body>Hello, I'm lgxZJ!</body></html>";
struct MHD_Response *response;
response = MHD_create_response_from_buffer(strlen(pageBuffer), (void*)pageBuffer,
MHD_RESPMEM_PERSISTENT);
if (MHD_add_response_header(response, "Content-Type", "text/html") == MHD_NO) {
std::cout << "MHD_add_response_header error\n";
return MHD_NO;
}
if (MHD_queue_response(connection, MHD_HTTP_OK, response) == MHD_NO) {
std::cout << "MHD_queue_response error\n";
return MHD_NO;
}
MHD_destroy_response(response);
return MHD_YES;
}
这个函数签名包含了所有用来处理请求的有用信息。microhttpd库提供了函数来方便我们响应请求,这里重点看创建响应。microhttpd库提供了两种方法来创建请求:从buffer创建、从文件创建。但是后者需要传入一个文件描述符,这在windows上不是很方便。
这里用缓冲创建。需要注意的是最后一个参数,这是一个MHD_ResponseMemoryMode枚举值,表示使用的buffer内容是固定不变的。这种枚举类型还包含其他2种代表瞬时缓冲类型的值,分别表示缓冲区是在heap上的,和非heap(例如stack)上的。 用不同的缓冲区时要记得用不同的枚举值。 接下来设置MIME类型,把缓冲入队,并释放MHD_Response结构体。对于正确响应,返回MHD_YES;不能响应的,返回MHD_NO。