web伺服器之mongoose:資料結構
原文網址:https://blog.csdn.net/yangxuan12580/article/details/51659762
Mongoose中有幾個資料結構扮演著重要的角色,它們分別是:
struct mg_context:儲存Mongoose的上下文,幾乎每個函式都有mg_context引數
struct mg_connection:儲存HTPP連線資訊
struct mg_request_info:儲存HTTP請求的資訊,這個結構體傳遞給URL處理函式
我之所以現在這裡介紹它,因為之後的分析工作中要用到它們,如果在讀完本文後還不能很好的理解,請將問題帶到後續文章中或程式碼分析中去,你會找到答案的。下面分別介紹它們。
本文的主要內容如下:
1、mg_context詳解
2、mg_connection詳解
3、mg_request_info詳解
4、其他資料結構
5、總結
1、mg_context詳解
mg_context結構體——表示Mongoose的上下文,也稱為一個例項控制代碼。它的成員如下:
- struct mg_context {
- int stop_flag; /* Should we stop event loop */
- SSL_CTX *ssl_ctx; /* SSL context */
- FILE *access_log; /* Opened access log */
- FILE *error_log; /* Opened error log */
- struct socket listeners[MAX_LISTENING_SOCKETS];
- int num_listeners;
- struct callback callbacks[MAX_CALLBACKS];
- int num_callbacks;
- char *options[NUM_OPTIONS]; /* Configured opions */
- pthread_mutex_t opt_mutex[NUM_OPTIONS]; /* Option protector */
- int max_threads; /* Maximum number of threads */
- int num_threads; /* Number of threads */
- int num_idle; /* Number of idle threads */
- pthread_mutex_t thr_mutex; /* Protects (max|num)_threads */
- pthread_cond_t thr_cond;
- pthread_mutex_t bind_mutex; /* Protects bind operations */
- struct socket queue[20]; /* Accepted sockets */
- int sq_head; /* Head of the socket queue */
- int sq_tail; /* Tail of the socket queue */
- pthread_cond_t empty_cond; /* Socket queue empty condvar */
- pthread_cond_t full_cond; /* Socket queue full condvar */
- mg_spcb_t ssl_password_callback;
- mg_callback_t log_callback;
- };
這個結構體在mg_start()中建立和初始化,其它函式大部分都會用它。因此mg_start()應該首先被呼叫。它非常重要,幾乎所有的函式都要用到它。
1)、stop_flag表示是否應該停止的標記,它有三個可能的值0、1、2。 stop_flag=0表示 不應該停止,這是初始值;stop_flag=1表示停止,在mg_stop()函式中的一開始設定stop_flag=1,這會觸發mg_fini(),且在mg_stop()中會一直等待mg_fini執行完成;stop_flag=2用於通知mg_stop(),mg_fini已經執行完成,stop_flag=2在mg_fini函式中的末尾設定。
2)、ssl_ctx是結構體ssl_ctx_st的例項,它來自OpenSSL開源專案,作者把它放到這裡的原因是使其獨立於OpenSSL的原始碼安裝,這樣只有系統上面安裝有SSL庫,mongoose+SSL就能編譯通過。
3)、access_log、error_log很明顯是指向訪問日誌檔案、錯誤日誌檔案。
4)、listeners陣列儲存mongoose建立的多個web server,每個web server都是listeners陣列中的一個元素。例如,一個伺服器可以分別在埠8080、8888建立web server,這樣8080埠的那個server是listerns陣列中的一個元素,8888埠的那個server也是listeners陣列中的一個元素。換句話說,listeners陣列表示web server的socket地址。num_listeners表示listeners陣列的元素個數。
5)、callbacks是結構體callback的陣列,而callback本身是一個結構體,包含幾個回撥控制代碼。num_callbacks是callbacks陣列元素的個數。
6)、options陣列,是用於儲存配置選項的,例如埠號、工作目錄等等。opt_mutext對配置進行操作的互斥變數。
7)、max_threads表示允許的最大執行緒數量、num_threads表示當前的執行緒數量、num_idle表示空閒的執行緒數量。之所以會有空閒程序,是因為當建立一個執行緒處理連線請求之後,它會保持一段時間空閒而不是直接銷燬。如果這裡再用新的連線到來或等待佇列中有需要處理的連線,空閒程序會被分配去處理。
8)、thr_mutex、thr_cond、bind_mutex是用於互斥訊號量和條件變數。
9)、queue[20]佇列陣列儲存client的連線請求,每個元素都是client的socket。sq_head、sq_tail分別是佇列頭、尾用於操作佇列queue。empty_cond、full_cond分別表示佇列是否為空、滿的條件變數。
10)、ssl_password_callback和log_callback都是函式指標,分別指向SSL密碼處理函式、log處理函式。他們原型是:
- /*
- * Register SSL password handler.
- * This is needed only if SSL certificate asks for a password. Instead of
- * prompting for a password on a console a specified function will be called.
- */
- typedef int (*mg_spcb_t)(char *buf, int num, int w, void *key);
- /*
- * User-defined callback function prototype for URI handling, error handling,
- * or logging server messages.
- */
- typedef void (*mg_callback_t)(struct mg_connection *,
- const struct mg_request_info *info, void *user_data);
是上面講了那麼多感覺挺亂的,下面用張圖片來形象表示一下:
圖1 mg_context結構體
2、mg_connection詳解
故名思意,這個結構體使用者儲存client的連線資訊。它的成員如下:
- /*
- * Client connection.
- */
- struct mg_connection {
- struct mg_request_info request_info;
- struct mg_context *ctx; /* Mongoose context we belong to*/
- SSL *ssl; /* SSL descriptor */
- struct socket client; /* Connected client */
- time_t birth_time; /* Time connection was accepted */
- bool_t free_post_data; /* post_data was malloc-ed */
- bool_t embedded_auth; /* Used for authorization */
- uint64_t num_bytes_sent; /* Total bytes sent to client */
- };
上面的欄位意思都很明顯這裡就不一一闡述了。可以看出, 每個連線都儲存了一個Mongoose上下文(mg_context * ctx),這個很重要,對連線請求進行處理時都會用到。這裡也可以看出mg_context相當於一個例項控制代碼。
結構體mg_request_info用於儲存每個請求的資訊,例如,當開啟http://www.google.com的時候,會發出一個請求資訊,包括請求的方法是POST還是GET等、uri即http://www.google.com、http版本、還有一些http頭資訊等等。關於結構體mg_request_info的詳細資訊參見下一小節。
mg_connection的影象表示如下:
圖2 mg_connection結構體的成員
3、mg_request_info詳解
這個結構體儲存每次client傳送請求,即是一個HTTP請求報文資訊。而我們知道HTTP的請求報文資訊的格式如下:
圖3 HTTP請求的格式
根據這個資訊,可以更好地理解mg_request_info。mg_request_info結構定義如下:
- /*
- * This structure contains full information about the HTTP request.
- * It is passed to the user-specified callback function as a parameter.
- */
- struct mg_request_info {
- char *request_method; /* "GET", "POST", etc */
- char *uri; /* Normalized URI */
- char *query_string; /* \0 - terminated */
- char *post_data; /* POST data buffer */
- char *remote_user; /* Authenticated user */
- long remote_ip; /* Client's IP address */
- int remote_port; /* Client's port */
- int post_data_len; /* POST buffer length */
- int http_version_major;
- int http_version_minor;
- int status_code; /* HTTP status code */
- int num_headers; /* Number of headers */
- struct mg_header {
- char *name; /* HTTP header name */
- char *value; /* HTTP header value */
- } http_headers[64]; /* Maximum 64 headers */
- };
從欄位都能夠故名思意,這裡就不再闡述了。
4、其他資料結構
除了上面3個主要的資料結構,還有其它一些資料也默默地貢獻著自己的一份力量。作為一個整體,少了它們Mongoose也只能淪為廢物。下面我就列舉幾個:
- /*
- * Structure used by mg_stat() function. Uses 64 bit file length.
- */
- struct mgstat {
- bool_t is_directory; /* Directory marker */
- uint64_t size; /* File size */
- time_t mtime; /* Modification time */
- };
- struct mg_option {
- const char *name;
- const char *description;
- const char *default_value;
- int index;
- bool_t (*setter)(struct mg_context *, const char *);
- };
- /*
- * Structure used to describe listening socket, or socket which was
- * accept()-ed by the master thread and queued for future handling
- * by the worker thread.
- */
- struct socket {
- SOCKET sock; /* Listening socket */
- struct usa lsa; /* Local socket address */
- struct usa rsa; /* Remote socket address */
- bool_t is_ssl; /* Is socket SSL-ed */
- };
- /*
- * Unified socket address. For IPv6 support, add IPv6 address structure
- * in the union u.
- */
- struct usa {
- socklen_t len;
- union {
- struct sockaddr sa;
- struct sockaddr_in sin;
- } u;
- };
- /*
- * Specifies a string (chunk of memory).
- * Used to traverse comma separated lists of options.
- */
- struct vec {
- const char *ptr;
- size_t len;
- };
- /*
- * Dynamically loaded SSL functionality
- */
- struct ssl_func {
- const char *name; /* SSL function name */
- void (*ptr)(void); /* Function pointer */
- };
5、總結
至此,我們介紹了Mongoose中使用的一些資料結構,搞清楚這些資料結構對整個專案的理解非常重要。它們遍佈在專案的每個角落(雖然專案比較小)