mongoose框架示例代碼解析(一)

mongoose框架示例代碼解析(一)


參考:

  1. Mongoose Networking Library Documentation(Server)
  2. Mongoose Networking Library Documentation(Client)

前言:

OK,感謝完恩公,來看看今天的正文吧~對了,把昨天寫時隔九年重新遇到半個初戀的博客置頂一下,時刻給自己一些刺激。這裏也放個鏈接,沒錯,皮這一下我很快樂!初步瞭解mac下C源碼的編譯過程_qq_31433709的博客-CSDN博客

不得不說,起名字真的是一門學問,這兩個源文件的方法名還有參數名稱都堪稱完美一目瞭然!

說起來,我vim上的C環境都還沒有弄呢,這擼代碼的過程感覺真的不夠快樂!晚上順便搞定吧!如果沒有找到(雖然這個相當不現實),那就順便學學怎麼編寫插件吧= =!


正文

一. 服務器端:

源碼文件:simplest_web_server.c

// Copyright (c) 2015 Cesanta Software Limited
// All rights reserved

#include "mongoose.h"

static const char *s_http_port = "8000";
static struct mg_serve_http_opts s_http_server_opts;

static void ev_handler(struct mg_connection *nc, int ev, void *p) {
  if (ev == MG_EV_HTTP_REQUEST) {
    mg_serve_http(nc, (struct http_message *) p, s_http_server_opts);
  }
}

int main(void) {
  struct mg_mgr mgr;
  struct mg_connection *nc;

  mg_mgr_init(&mgr, NULL);
  printf("Starting web server on port %s\n", s_http_port);
  nc = mg_bind(&mgr, s_http_port, ev_handler);
  if (nc == NULL) {
    printf("Failed to create listener\n");
    return 1;
  }

  // Set up HTTP server parameters
  mg_set_protocol_http_websocket(nc);
  s_http_server_opts.document_root = ".";  // Serve current directory
  s_http_server_opts.enable_directory_listing = "yes";

  for (;;) {
    mg_mgr_poll(&mgr, 1000);
  }
  mg_mgr_free(&mgr);

  return 0;
}

(1)先初步掃一眼:

嗚嗚,好多已經被封進框架的方法調用,常量和結構體:

  1. 結構體:
  • mg_mgr
  • mg_connection
  • mg_serve_http_opts
  1. 方法調用:
  • mg_mgr_init
  • mg_bind
  • mg_serve_http
  • mg_set_protocol_http_websocket
  • mg_mgr_pool
  • mg_mgr_free
  1. 常量:
  • MG_EV_HTTP_REQUEST

只導入了一個頭文件,去這裏面找找唄= =,哇,6277行,ok,小朋友,你是不是有很多疑問?
頭文件中能獲取到的我感覺最多隻有常量,而方法的實現和結構體的定義,我還是感覺要從.c文件中去獲取。

(2)那就先看看頭文件吧

vim全局搜一下,MG_EV_HTTP_REQUEST的結果,找到定義就行了,其餘的嘛,本來想也列出來,不過爲了篇幅的簡約,還是省略比較好,個人感覺(大概瞄了一下~),然後我發現無論是結構體還是方法調用抑或是常量,在頭文件裏面都有很具體的講解,甚至有示例代碼,所以建議直接在mongoose.h文件中自行搜索,然後對於mg_mgr_pool的1000參數,還是需要看.c文件中的具體實現

然後這是我大體理了一圈的結果,畢竟是第一次寫這方面的內容,差是差了點,不過畢竟是爲了自我的提升(自我安慰),總有從差到好的過程嘛!

// Copyright (c) 2015 Cesanta Software Limited
// All rights reserved

//導入mongoose所依賴的必須頭文件
#include "mongoose.h"

//指定默認的服務器http端口號
static const char *s_http_port = "8000";
//指定http鏈接的各種選項
static struct mg_serve_http_opts s_http_server_opts;

//ev_handler指定的event handler,即事件處理,mg指代的是mongoose
static void ev_handler(struct mg_connection *nc, int ev, void *p) {
  if (ev == MG_EV_HTTP_REQUEST) {
    mg_serve_http(nc, (struct http_message *) p, s_http_server_opts);
  }
}

//總入口,一切的開始
int main(void) {
  struct mg_mgr mgr;
  struct mg_connection *nc;

  //初始化mg_mar變量
  mg_mgr_init(&mgr, NULL);
  printf("Starting web server on port %s\n", s_http_port);
  //這裏有點函數式的感覺,傳入的不是對象,而是方法指針
  //將mgr和其中的mgr_connection以及對應的端口號還有對應的不同event的處理器所綁定,並返回對應的綁定後的mg_connection對象
  nc = mg_bind(&mgr, s_http_port, ev_handler);

  if (nc == NULL) {
    printf("Failed to create listener\n");
    return 1;
  }

  // Set up HTTP server parameters
  mg_set_protocol_http_websocket(nc);
  //設置客戶端訪問服務器的初始路徑,這裏設置爲"."即爲可執行文件的當前路徑
  s_http_server_opts.document_root = ".";  // Serve current directory
  //同時設置是否支持顯示當前目錄下的文件信息
  s_http_server_opts.enable_directory_listing = "yes";

  for (;;) {
    //這裏的1000是什麼意思呢?
    //翻譯一下文檔中對這個方法的描述:
    //這個方法執行實際上的IO操作並且必須在一個循環中被調用(一個事件循環)。
    //它返回了生成的用戶事件數目(除了POLL)。
    //第二個參數是以毫秒爲單位的睡眠最大時間。
    //該方法爲IO操作檢查了所有的連接(connection)。如果至少有一個連接已經準備好IO操作,此方法將切換到對應的事件處理器然後返回。
    mg_mgr_poll(&mgr, 1000);
    //所以說,1000到底是什麼意思?看來光看頭文件比較難啊。
    //ok,大概看了看實現,1000是設置的請求超時時間
  }
  //解構mg_mgr,該方法中應該同時解構了mg_connection,並釋放了對應占用的內存,道理的確是這樣,但是什麼情況下會跳出這個死循環呢?如果我直接通過信號,貌似不會走這步,並沒有看見輸出stopped的信息
  mg_mgr_free(&mgr);
    printf("stopped mongoose server");
  return 0;
}


小結:

OK,感覺今天看到這個程序差不多了,也適當看到了一些細節,服務端的流程也基本理了一圈了。早睡早起身體好~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章