使用Libmicrohttpd搭建內(nèi)嵌(本地)服務(wù)器的方法
Libmicrohttpd簡介
GNU Libmicrohttpd是一個用來在項(xiàng)目中內(nèi)嵌http服務(wù)器的C語言庫,它具有以下幾個非常鮮明的特點(diǎn):
C語言庫,小而快。
API非常簡單,且都是可重入的。
兼容HTTP1.1。
支持4種多線程模型(select、poll、pthread、thread poll)。
跨平臺。
生成的二制文件只有32K(不包含TLS/SSL等額外功能)。
搭建一個簡單的本地靜態(tài)服務(wù)器
這篇文章里,我們只編寫一個簡單的靜態(tài)服務(wù)器,對于用戶的所有請求我們都只返回同一個html頁面, 該頁面顯示一串字符。
1. 下載Libmicrohttpd,編譯后添加進(jìn)VS項(xiàng)目
為了使用Libmicrohttpd,我們需要將其添加進(jìn)VS項(xiàng)目中。這里我們選擇編譯源代碼生成靜態(tài)庫,因?yàn)楣俜浇o的下載靜態(tài)庫版本鏈接在使用時會有問題,可能是運(yùn)行庫版本不一致; 并且在使用靜態(tài)庫的情況下,我們只需要引用兩個文件就可以了(一個頭文件、一個庫文件),項(xiàng)目結(jié)構(gòu)不會混亂不清。
實(shí)際上Libmicrohttpd的源碼編譯非常簡單,它提供了VS編譯文件,基本上我們只需要進(jìn)入<>w32目錄,在該目錄下選擇合適的VS子目錄下的sln文件,雙擊打開就可以了。打開后,修改設(shè)置libmicrohttpd項(xiàng)目為靜態(tài)庫項(xiàng)目(記得修改生成文件的后綴名,因?yàn)槟J(rèn)是dll),右擊生成就可以編譯成功了。
生成的文件包括一個頭文件和一個靜態(tài)庫文件,新建一個VS控制臺項(xiàng)目,并將它們添加到VS項(xiàng)目中。
2. main函數(shù)
main函數(shù)非常簡單,核心調(diào)用只有2個函數(shù):<>MHD_start_daemon,MHD_stop_daemon,分別開始和停止http服務(wù)器。
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函數(shù)包含非常多的參數(shù),這也意味著它集成了很多的功能,這里我們只關(guān)注四個參數(shù),其它都為NULL:
MHD_USE_INTERNAL_POLpNG_THREAD。這個參數(shù)與其他兩個參數(shù)(MHD_USE_POLL_INTERNAL_THREAD、MHD_USE_EPOLL_INTERNAL_THREAD)一起構(gòu)成了microhttpd支持的三種模式:select、poll、epoll。用戶必須選擇這三種模式之一。具體信息見源碼。
port。端口號。
connectHandler。處理請求的函數(shù)。
MHD_OPTION_END。由于MHD_start_daemon最后一個參數(shù)是一個變參,因此MHD_OPTION_END用來表示變參終止。
MHD_stop_daemon函數(shù)比較簡單,這里不介紹了。
3 請求處理函數(shù)
所有的請求處理都發(fā)生在<>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;
}
這個函數(shù)簽名包含了所有用來處理請求的有用信息,這里不逐一介紹了。microhttpd庫提供了函數(shù)來方便我們響應(yīng)請求,這里我們重點(diǎn)看創(chuàng)建響應(yīng)。microhttpd庫提供了兩種方法來創(chuàng)建請求:從buffer創(chuàng)建、從文件創(chuàng)建。但是后者需要傳入一個文件描述符,這在windows上不是很方便。
我們這里用緩沖創(chuàng)建。需要注意的是最后一個參數(shù),這是一個<>MHD_ResponseMemoryMode枚舉值,表示我們使用的buffer內(nèi)容是固定不變的。這種枚舉類型還包含其他2種代表瞬時緩沖類型的值,分別表示緩沖區(qū)是在heap上的,和非heap(例如stack)上的。 用不同的緩沖區(qū)時要記得用不同的枚舉值。 接下來設(shè)置MIME類型,把緩沖入隊(duì),并釋放MHD_Response結(jié)構(gòu)體。對于正確響應(yīng),我們返回MHD_YES;不能響應(yīng)的,我們返回MHD_NO。
運(yùn)行程序,我們打開瀏覽器并輸入<>127.0.0.1:8888,得到如下結(jié)果:

還能做更多
MHD_start_daemon函數(shù)還可以限制特定ip的訪問。
請求處理函數(shù)還包含請求方法和請求數(shù)據(jù)。
我們還可以掛起、恢復(fù)連接。
以上這篇使用Libmicrohttpd搭建內(nèi)嵌(本地)服務(wù)器的方法就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于Windows C++ 應(yīng)用程序通用日志組件的使用詳解
眾所周知,在調(diào)試、跟蹤和執(zhí)行應(yīng)用程序的過程中,程序的日志能為這些工作提供大量有價值的運(yùn)行信息。因此,程序的日志對應(yīng)用程序的運(yùn)行、維護(hù)至關(guān)重要2013-05-05
C++ 類的賦值運(yùn)算符''''=''''重載的方法實(shí)現(xiàn)
這篇文章主要介紹了C++ 類的賦值運(yùn)算符'='重載的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
C語言超詳細(xì)講解循環(huán)與分支語句基礎(chǔ)
各位小伙伴們,今天給大家?guī)淼氖茄h(huán)與分支語句,本篇將會向大家介紹這些語句的格式和使用的基本方法,感興趣的朋友來看看吧2022-04-04
C++?TCP網(wǎng)絡(luò)編程詳細(xì)講解
TCP/IP是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,它會保證數(shù)據(jù)不丟包、不亂序。TCP全名是Transmission?Control?Protocol,它是位于網(wǎng)絡(luò)OSI模型中的第四層2022-09-09
C語言實(shí)現(xiàn)文本文件/二進(jìn)制文件格式互換
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)文本文件和二進(jìn)制文件格式互換,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-03-03

