要創建HTTP服務器,請按照以下格式:
- 通過調用
mg_bind()
或mg_bind_opt()創建偵聽連接
調用mg_set_protocol_http_websocket()
創建listening連接。它附帶一個內置的HTTP事件處理程序,它解析傳入的數據並觸發HTTP特定的事件。例如,當HTTP請求完全緩沖時,內置的HTTP處理程序會解析請求,並調用用戶定義的事件處理程序,並將MG_EV_HTTP_REQUEST
事件和解析的HTTP請求作為事件數據。- 創建事件處理函數。請注意,事件處理程序接收所有事件 - 低級TCP事件
MG_EV_RECV
和高級HTTP事件,如MG_EV_HTTP_REQUEST
。通常情況下,事件處理函數只能處理MG_EV_HTTP_REQUEST
事件。
以下是最簡單HTTP服務器的示例。為了清楚起見,省略了錯誤檢查:
#include "mongoose.h" static const char *s_http_port = "8000"; static void ev_handler(struct mg_connection *c, int ev, void *p) { if (ev == MG_EV_HTTP_REQUEST) { struct http_message *hm = (struct http_message *) p; // We have received an HTTP request. Parsed request is contained in `hm`. // Send HTTP reply to the client which shows full original request. mg_send_head(c, 200, hm.message.len, "Content-Type: text/plain"); mg_printf(c, "%.*s", hm.message.len, hm.message.p); } } int main(void) { struct mg_mgr mgr; struct mg_connection *c; mg_mgr_init(&mgr, NULL); c = mg_bind(&mgr, s_http_port, ev_handler); mg_set_protocol_http_websocket(c); for (;;) { mg_mgr_poll(&mgr, 1000); } mg_mgr_free(&mgr); return 0; }
要創建HTTP客戶端,請遵循以下模式:
- 通過調用創建出站連接
mg_connect_http()
- 創建一個處理
MG_EV_HTTP_REPLY
事件的事件處理函數
以下是最簡單HTTP客戶端的示例。為了清楚起見,省略錯誤檢查:
#include "mongoose.h" static const char *url = "http://www.google.com"; static int exit_flag = 0; static void ev_handler(struct mg_connection *c, int ev, void *p) { if (ev == MG_EV_HTTP_REPLY) { c->flags |= MG_F_CLOSE_IMMEDIATELY; fwrite(hm->message.p, 1, hm->message.len, stdout); putchar('\n'); exit_flag = 1; } else if (ev == MG_EV_CLOSE) { exit_flag = 1; }; } int main(void) { struct mg_mgr mgr; mg_mgr_init(&mgr, NULL); mg_connect_http(mgr, ev_handler, url, NULL, NULL); while (exit_flag == 0) { mg_mgr_poll(&mgr, 1000); } mg_mgr_free(&mgr); return 0; }
HTTP事件
如概述所述,mg_set_protocol_http_websocket()
函數解析輸入數據,將其視為HTTP或WebSocket,並觸發高級HTTP或WebSocket事件。以下是HTTP特有的事件列表。
- MG_EV_HTTP_REQUEST:HTTP請求到達。解析的請求
struct http_message
通過處理程序的void *ev_data
指針傳遞 。 - MG_EV_HTTP_REPLY:HTTP回復已到。解析的回復
struct http_message
通過處理程序的void *ev_data
指針傳遞。 - MG_EV_HTTP_MULTIPART_REQUEST:多部分POST請求已到。此事件在body解析之前發送。此后,用戶應該期望一系列MG_EV_HTTP_PART_BEGIN / DATA / END請求。這也是頭文件和其他請求字段可訪問的最后一次。
- MG_EV_HTTP_CHUNK:一個HTTP分塊編碼塊到了。解析的HTTP回復
struct http_message
通過處理程序的void *ev_data
指針傳遞。http_message::body
將包含不完整的,重新組合的HTTP身體。它將隨着到達的每一個新的塊增長,並且可能消耗大量的內存。事件處理程序可以處理以分塊形式到來的body,並通知Mongoose通過設定在mg_connection::flags中的MG_F_DELETE_CHUNK來刪除body
。當接收到最后一個零塊時,Mongoose會發送MG_EV_HTTP_REPLY
具有完全重新組合的身體的事件(如果處理程序沒有指示刪除塊)或空的身體(如果處理程序發出信號刪除塊)。 - MG_EV_HTTP_PART_BEGIN:多部分消息的新部分啟動,額外的參數將以mg_http_multipart_part發送
- MG_EV_HTTP_PART_DATA:來自多部分消息的新部分數據沒有附加頭可用,只有數據和數據大小
- MG_EV_HTTP_PART_END:接收到最后一個邊界,可能用於找到包的結尾注意:Mongoose應使用MG_ENABLE_HTTP_STREAMING_MULTIPART進行編譯,以啟用多部分事件。
提供文件
API函數mg_serve_http()
可以輕松地從文件系統提供文件。一般來說,該功能是提供靜態文件CGI和SSI的HTTP服務器的實現。它的行為是由整合到結構中的選項列表驅動的struct mg_serve_http_opts
。有關完整的功能列表,請參閱struct mg_serve_http_opts定義mg_serve_http()
。
例如,為了創建一個從當前目錄提供靜態文件的Web服務器,實現如下的事件處理函數:
static void ev_handler(struct mg_connection *c, int ev, void *ev_data) { if (ev == MG_EV_HTTP_REQUEST) { struct mg_serve_http_opts opts; memset(&opts, 0, sizeof(opts); // Reset all options to defaults opts.document_root = "."; // Serve files from the current directory mg_serve_http(c, (struct http_message *) ev_data, s_http_server_opts); } }
其他選項請參考:
https://docs.cesanta.com/mongoose/master/#/overview/event-handler.md/