mongoose 開源http庫(2) --HTTP服務示例


要創建HTTP服務器,請按照以下格式:

  1. 通過調用mg_bind()mg_bind_opt()創建偵聽連接
  2. 調用mg_set_protocol_http_websocket()創建listening連接。它附帶一個內置的HTTP事件處理程序,它解析傳入的數據並觸發HTTP特定的事件。例如,當HTTP請求完全緩沖時,內置的HTTP處理程序會解析請求,並調用用戶定義的事件處理程序,並將MG_EV_HTTP_REQUEST事件和解析的HTTP請求作為事件數據。
  3. 創建事件處理函數。請注意,事件處理程序接收所有事件 - 低級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客戶端,請遵循以下模式:

  1. 通過調用創建出站連接 mg_connect_http()
  2. 創建一個處理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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM