為了學習高效能並發伺服器,打算研究一下Nginx的實作。按照慣例,一開始都要寫一個hello world的程序,所以接下來就是介紹如何在Nginx的框架下寫一個簡單的HTTP模組來列印」Hello World「。
定義hello配置項目的處理
首先,我們要定義一個commands陣列用來定義模組的設定檔參數。每一個數組元素都是ngx_command_t類型,數組的結尾用ngx_null_command結尾。
Nginx在解析設定檔中的一個配置項時首先會遍歷所有的模組,對於每個模組而言,即透過遍歷commands數組進行。每一個ngx_command_t結構體定義了自己感興趣的一個配置項。這個結構定義如下:
<code><span>struct</span> ngx_command_s { <span>/* 配置项名称 */</span> ngx_str_t name; <span>/* 指定配置项可以出现的位置 */</span> ngx_uint_t type; <span>/* 出现了name中指定的配置项后,将会调用set方法处理配置项的参数 */</span><span>char</span> *(*<span>set</span>)(ngx_conf_t *cf, ngx_command_t *cmd, <span>void</span> *conf); ngx_uint_t conf; <span>/* 在配置文件中的偏移量 */</span> ngx_uint_t offset; <span>/* 配置项读取后的处理过程,必须是ngx_conf_post_t结构的指针 */</span><span>void</span> *post; }; <span>#define ngx_null_command { ngx_null_string, 0, NULL, 0, 0, NULL }</span></code>
了解了commands數組後,我們定義hello配置項的處理:
<code><span>static</span> ngx_command_t ngx_http_hello_commands[] = { { ngx_string(<span>"hello"</span>), NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, ngx_http_hello, NGX_HTTP_LOC_CONF_OFFSET, <span>0</span>, NULL }, ngx_null_command };</code>
其中,ngx_http_hello是ngx_command_t結構體中的set成員,當在某個配置塊中出現hello配置項時, Nginx會呼叫ngx_http_hello方法。下面是ngx_http_hello的實作:
<code><span>static</span><span>char</span> * ngx_http_hello(ngx_conf_t *cf, ngx_command_t *cmd, <span>void</span> *conf) { ngx_http_core_loc_conf_t *clcf; <span>/* 首先找到hello配置项所属的配置块 */</span> clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); <span>/* HTTP框架在处理用户请求进行到NGX_HTTP_CONTENT_PHASE阶段时 * 如果请求的主机域名、URI与hello配置项所在的配置块相匹配 * 则调用ngx_http_hello_handler方法处理这个请求 */</span> clcf->handler = ngx_http_hello_handler; <span>return</span> NGX_CONF_OK; }</code>
定義hello模組
定義一個HTTP模組的方式很簡單,只要像下面這樣定義一個ngx_moodule_t的結構體:
<code>ngx_module_t ngx_http_hello_module = { NGX_MODULE_V1, &ngx_http_hello_module_ctx, <span>/* module context */</span> ngx_http_hello_commands, <span>/* module directives */</span> NGX_HTTP_MODULE, <span>/* module type */</span> NULL, <span>/* init master */</span> NULL, <span>/* init module */</span> NULL, <span>/* init process */</span> NULL, <span>/* init thread */</span> NULL, <span>/* exit thread */</span> NULL, <span>/* exit process */</span> NULL, <span>/* exit master */</span> NGX_MODULE_V1_PADDING };</code>
則hello模組在編譯時將會被加入全域到編譯時將會被加入全域到編譯數組中。
其中ngx_http_hello_commands
就是前一節我們定義的hello配置項目的處理。
因為我們定義的是HTTP模組,所以type
要設定成NGX_HTTP_MODULE
。
還有一個重要的成員void* ctx
,對於HTTP模組來說,ctx指標必須指向ngx_http_module_t
介面。
HTTP框架在讀取、重載設定檔時定義了由ngx_http_module_t介面描述的8個階段,HTTP框架在啟動的時候會在每個階段中呼叫ngx_http_module_t中對應的方法。如果不需要做什麼工作,則可以定義為NULL。因為hello模組不需要做什麼工作,所以定義如下:
<code><span>static</span> ngx_http_module_t ngx_http_hello_module_ctx = { NULL, <span>/* preconfiguration */</span> NULL, <span>/* postconfiguration */</span> NULL, <span>/* create main configuration */</span> NULL, <span>/* init main configuration */</span> NULL, <span>/* create server configuration */</span> NULL, <span>/* merge server configuration */</span> NULL, <span>/* create location configuration */</span> NULL <span>/* merge location configuration */</span> };</code>
處理用戶請求
最後就是處理用戶請求了,這裡需要一點HTTP的知識,可以參考HTTP協定入門。我們是透過實作ngx_http_hello_handler
方法來處理使用者的請求了,該方法定義如下:
<code><span>static</span> ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r)</code>
其中ngx_http_request_t
結構體中包含了請求的所有資訊(如方法,URI,協定版本號和頭部等) ,除此之外,還包含了其他很多成員,例如記憶體池,回應標頭等等。
因為我們只處理GET方法和HEAD方法,所以需要做以下判斷:
<code><span>if</span> (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) { <span>return</span> NGX_HTTP_NOT_ALLOWED; }</code>
接下來因為我們不需要請求中的包體,所以需要丟棄掉包體,方法如下:
<code>ngx_int_t rc = ngx_http_discard_request_body(r); <span>if</span> (rc != NGX_OK) { <span>return</span> rc; }</code>
然後是設定返回的回應包,回傳的包體只包含一個」Hello World」字串:
<code>ngx_str_type = ngx_string(<span>"text/plain"</span>); ngx_str_response = ngx_string(<span>"Hello World"</span>); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = response.len; r->headers_out.content_type = type;</code>
最後就是發送回應包的包頭和包體了:
<code> rc = ngx_http_send_header(r); <span>if</span> (rc == NGX_ERR || rc > NGX_OK || r->header_only) { <span>return</span> rc; } ngx_buf_t *b; b = ngx_create_temp_buf(r->pool, response.len); <span>if</span> (b == NULL) { <span>return</span> NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_memcpy(b->pos, response.data, response.len); b->last = b->pos + response.len; b->last_buf = <span>1</span>; ngx_chain_t out; out.buf = b; out.next = NULL; <span>/* send the buffer chain of your response */</span><span>return</span> ngx_http_output_filter(r, &out);</code>
完整程式碼可以在這裡查看:hello_module
編譯和運行
在程式碼同目錄下新建一個config
文件,加入這樣幾行:
<code>ngx_addon_name=ngx_http_hello_module HTTP_MODULES=<span>"<span>$HTTP_MODULES</span> ngx_http_hello_module"</span> NGX_ADDON_SRCS=<span>"<span>$NGX_ADDON_SRCS</span><span>$ngx_addon_dir</span>/ngx_http_hello_module.c"</span></code>
然後進入Nginx的源碼根目錄,運行configure
,記得帶上–add-module參數,在參數後面接上我們自己編寫的HTTP模組程式碼所在的路徑:
<code>./configure --prefix=<span>/usr/local</span><span>/nginx --add-module=/code</span><span>/nginx-1.8.0/src</span><span>/http/hello</span>_module</code>
configure運行完成後,用make
指令來編譯,編譯成功後輸入make install
完成安裝。
修改/usr/local/nginx/conf/nginx.conf
,新增:
<code>http{ <span>...</span> server { <span>...</span> location /hello { hello; } <span>...</span> } <span>...</span> }</code>
運行Nginx,然後在瀏覽器輸入IP/hello
就可以看到顯示的」Hello World字串了「。
參考
《深入理解Nginx》
以上就介紹了 hello模組的編寫,包括了方面的內容,希望對PHP教程有興趣的朋友有所幫助。

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

PHP在現代化進程中仍然重要,因為它支持大量網站和應用,並通過框架適應開發需求。 1.PHP7提升了性能並引入了新功能。 2.現代框架如Laravel、Symfony和CodeIgniter簡化開發,提高代碼質量。 3.性能優化和最佳實踐進一步提升應用效率。

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP中使用clone關鍵字創建對象副本,並通過\_\_clone魔法方法定制克隆行為。 1.使用clone關鍵字進行淺拷貝,克隆對象的屬性但不克隆對象屬性內的對象。 2.通過\_\_clone方法可以深拷貝嵌套對象,避免淺拷貝問題。 3.注意避免克隆中的循環引用和性能問題,優化克隆操作以提高效率。

PHP適用於Web開發和內容管理系統,Python適合數據科學、機器學習和自動化腳本。 1.PHP在構建快速、可擴展的網站和應用程序方面表現出色,常用於WordPress等CMS。 2.Python在數據科學和機器學習領域表現卓越,擁有豐富的庫如NumPy和TensorFlow。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用