mongoose框架示例代碼解析(一)
參考:
前言:
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)先初步掃一眼:
嗚嗚,好多已經被封進框架的方法調用,常量和結構體:
- 結構體:
- mg_mgr
- mg_connection
- mg_serve_http_opts
- 方法調用:
- mg_mgr_init
- mg_bind
- mg_serve_http
- mg_set_protocol_http_websocket
- mg_mgr_pool
- mg_mgr_free
- 常量:
- 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,感覺今天看到這個程序差不多了,也適當看到了一些細節,服務端的流程也基本理了一圈了。早睡早起身體好~