1. Nginx 介紹 Nginx是俄羅斯人編寫的十分輕量級的HTTP服務器,它的發(fā)音為“engine X”, 是一個高性能的HTTP和反向代理服務器,同時也是一個IMAP/POP3/SMTP 代理服務器.Nginx是由俄羅斯人 Igor Sysoev為俄羅斯訪問量第二的 Rambler.ru站點開發(fā)的,從2004年開始它已經(jīng)在該站點運行了七八年了。Igor Sysoev在建立的項目時,使用基于BSD許可。 英文主頁:http://nginx.org. Nginx以事件驅(qū)動的方式編寫,所以有非常好的性能,同時也是一個非常高效的反向代理、負載平衡。 現(xiàn)在,Igor將源代碼以類BSD許可證的形式發(fā)布。Nginx因為它的穩(wěn)定性、豐富的模塊庫、靈活的配置和低系統(tǒng)資源的消耗而聞名.業(yè)界一致認為它是Apache+mod_proxy_balancer的輕量級代替者,不僅是因為響應靜態(tài)頁面的速度非常快,而且它的模塊數(shù)量也非常非常豐富。對proxy?和 rewrite模塊的支持很徹底,還支持mod_fcgi、ssl、vhosts ,適合用來做mongrel clusters的前端HTTP響應。
? nginx做為HTTP服務器,有以下幾項基本特性:
處理靜態(tài)文件,索引文件以及自動索引;打開文件描述符緩沖. 無緩存的反向代理加速,簡單的負載均衡和容錯. FastCGI,簡單的負載均衡和容錯. 模塊化的結(jié)構(gòu)。包括gzipping, byte ranges, chunked responses,以及 SSI-filter等filter。如果由FastCGI或其它代理服務器處理單頁中存在的多個SSI,則這項處理可以并行運行,而不需要相互等待。 支持SSL 和 TLSSNI.
? Nginx專為性能優(yōu)化而開發(fā),性能是其最重要的考量,實現(xiàn)上非常注重效率。它支持內(nèi)核 epoll、kqueue 等高性能并發(fā)模型,能經(jīng)受高負載的考驗。
? Nginx具有很高的穩(wěn)定性。其它HTTP服務器,當遇到訪問的峰值,或者有人惡意發(fā)起慢速連接時,也很可能會導致服務器物理內(nèi)存耗盡頻繁交換,失去響 應,只能重啟服務器。例如當前apache一旦上到200個以上進程,web響應速度就明顯非常緩慢了。而Nginx采取了分階段資源分配技術(shù),使得它的 CPU與內(nèi)存占用率非常低。nginx官方表示保持10,000個沒有活動的連接,它只占2.5M內(nèi)存,所以類似DOS這樣的攻擊對nginx來說基本上 是毫無用處的。就穩(wěn)定性而言,nginx比lighthttpd更勝一籌。
? Nginx支持熱部署。它的啟動特別容易, 并且?guī)缀蹩梢宰龅?*24不間斷運行,即使運行數(shù)個月也不需要重新啟動。你還能夠在不間斷服務的情況下,對軟件版本進行進行升級。
? Nginx采用master-slave模型,能夠充分利用SMP的優(yōu)勢,且能夠減少工作進程在磁盤I/O的阻塞延遲。當采用select()/poll()調(diào)用時,還可以限制每個進程的連接數(shù)。
? Nginx代碼質(zhì)量非常高,代碼很規(guī)范,手法成熟, 模塊擴展也很容易。特別值得一提的是強大的Upstream與Filter鏈。 Upstream為諸如reverse proxy,與其他服務器通信模塊的編寫奠定了很好的基礎。而Filter鏈最酷的部分就是各個filter不必等待前一個filter執(zhí)行完畢。它可以 把前一個filter的輸出做為當前filter的輸入,這有點像Unix的管線。這意味著,一個模塊可以開始壓縮從后端服務器發(fā)送過來的請求,且可以在 模塊接收完后端服務器的整個請求之前把壓縮流轉(zhuǎn)向客戶端。
? 當然,nginx還很年輕,多多少少存在一些問題,比如:Nginx是俄羅斯人創(chuàng)建,目前文檔方面還不是很完善.因為文檔大多是俄語,所以文檔方面這也是個障礙.盡管nignx的模塊比較多,但它們還不夠完善。對腳本的支持力度不夠。
這些問題,nginx的作者和社區(qū)都在努力解決,我們有理由相信nginx將繼續(xù)以高速的增長率來分享輕量級HTTP服務器市場,會有一個更美好的未來。 2. 準備工作 去官方主頁?http://nginx.org/?下載最新的Nginx源碼包,這里給出目前最新的源碼包的直接連接:?http://nginx.org/download/nginx-1.0.0.tar.gz?
?
[zieckey@freebsd7.2 ~]$?mkdir nginx [zieckey@freebsd7.2 ~]$?cd nginx [zieckey@freebsd7.2 ~/nginx]$?wget http://nginx.org/download/nginx-1.0.0.tar.gz [zieckey@freebsd7.2 ~/nginx]$?tar zxf nginx-1.0.0.tar.gz [zieckey@freebsd7.2 ~/nginx]$?mkdir module_dev_urlquery [zieckey@freebsd7.2 ~/nginx]$?cd module_dev_urlquery/ [zieckey@freebsd7.2 module_dev_urlquery]$
這里我們下載了 nginx-1.0.0 的源碼,然后準備開發(fā)一個?module_dev_urlquery 的module嵌入到nginx中?
3. 準備好?module_dev_urlquery?模塊的配置文件? 一個 nginx module 一般都以個文件夾的方式存在,module源文件和該module的配置文件都在這個文件下面。 這里我們的module叫?module_dev_urlquery,其路徑為 /home/zieckey/nginx/module_dev_urlquery 。 其配置文件名為:config ,其路徑為?/home/zieckey/nginx/module_dev_urlquery/config [zieckey@freebsd7.2 module_dev_urlquery]$ vim config 然后輸入以下內(nèi)容:
?
[zieckey@freebsd7.2 module_dev_urlquery]$?vim config ngx_addon_name=ngx_http_p2s_module HTTP_MODULES="$HTTP_MODULES ngx_http_p2s_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_p2s_module.c"
?
這里三行內(nèi)容稍稍解釋下: 第一行是表示這個 nginx module 在程序中名字 第二行表示這是一個HTTP module,后面的名字與第一個行保存一致 第三是這個module的源文件路徑,值得說明的是?$ngx_addon_dir 這個變量是 nginx 的內(nèi)置腳本的內(nèi)置變量,代表了這個 module 的文件夾的絕對路徑,這里就是?/home/zieckey/nginx/module_dev_urlquery 4. 準備源代碼文件?ngx_http_p2s_module.c? 這里的文件名和路徑必須與上面 config 文件中的一致 [zieckey@freebsd7.2 module_dev_urlquery]$ vim ngx_http_p2s_module.c 輸入以下源程序內(nèi)容:
?
#include?<ngx_core.h> #include?<ngx_http.h> #include?<nginx.h> typedef?struct?{ ????unsigned?long?consume; ????char*?ini_buf; ????size_t?buflen;//the lenght of the ini_buf }?ngx_http_p2s_conf_t; static?char?*ngx_http_p2s_urlquery_set(ngx_conf_t?*cf,?ngx_command_t?*cmd,?void?*conf); static?void?*ngx_http_p2s_create_conf(ngx_conf_t?*cf); static?uint8_t*?get_raw_http_body(?ngx_http_request_t*?r,?size_t*?body_len?); static?ngx_command_t ngx_http_p2s_commands[]?= {/*{{{*/ ????{?ngx_string("p2s_urlquery"),?//The command name, it MUST BE the same as nginx.conf location block's command ????NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, ????ngx_http_p2s_urlquery_set, ????0, ????0, ????NULL?}, ????ngx_null_command };/*}}}*/ static?ngx_http_module_t ngx_http_p2s_module_ctx?= {/*{{{*/ ????NULL,?/* preconfiguration */? ????NULL,?/* postconfiguration */ ????NULL,?/* create main configuration */ ????NULL,?/* init main configuration */ ????NULL,?/* create server configuration */ ????NULL,?/* merge server configuration */ ????ngx_http_p2s_create_conf,?/* create location configration */ ????NULL?/* merge location configration */ };/*}}}*/ ngx_module_t ngx_http_p2s_module?= {/*{{{*/ ????NGX_MODULE_V1, ????&ngx_http_p2s_module_ctx,?/* module context */ ????ngx_http_p2s_commands,?/* module directives */ ????NGX_HTTP_MODULE,?/* module type */ ????NULL,?/* init master */ ????NULL,?/* init module */ ????NULL,?/* init process */ ????NULL,?/* init thread */ ????NULL,?/* exit thread */ ????NULL,?/* exit process */ ????NULL,?/* exit master */ ????NGX_MODULE_V1_PADDING };/*}}}*/ /** * @brief Get the HTTP body data from the ngx_http_request_t struct. * @warning DONNOT release the return pointer. * @param[in] ngx_http_request_t * r - * The HTTP request of NGINX struct which holds the HTTP data. * @param[out] size_t * body_len - The body data length will stored here. * @return uint8_t* - A pointer to a memory where? * stored the HTTP body raw binary data. * The memory is allocated from nginx memory pool, * so the caller don't need to warry about the memory release work. */ static?uint8_t*?get_raw_http_body(?ngx_http_request_t*?r,?size_t*?body_len?) {/*{{{*/ ????printf(?"%s\n",?__PRETTY_FUNCTION__?); ????ngx_chain_t*?bufs?=?r->request_body->bufs; ????*body_len?=?0; ????ngx_buf_t*?buf?=?NULL; ????uint8_t*?data_buf?=?NULL; ????size_t?content_length?=?0; ????if?(?r->headers_in.content_length?==?NULL?) ????{ ????????return?NULL; ????} ????// malloc space for data_buf ????content_length?=?atoi(?(char*)(r->headers_in.content_length->value.data)?); ????data_buf?=?(?uint8_t*?)ngx_palloc(?r->pool?,?content_length?+?1?); ????size_t?buf_length?=?0; ????while?(?bufs?) ????{ ????????buf?=?bufs->buf; ????????bufs?=?bufs->next; ????????buf_length?=?buf->last?-?buf->pos?; ????????if(?*body_len?+?buf_length?>?content_length?) ????????{ ????????????memcpy(?data_buf?+?*body_len,?buf->pos,?content_length?-?*body_len?); ????????????*body_len?=?content_length?; ????????????break; ????????} ????????memcpy(?data_buf?+?*body_len,?buf->pos,?buf->last?-?buf->pos?); ????????*body_len?+=?buf->last?-?buf->pos; ????} ????if?(?*body_len?) ????{ ????????data_buf[*body_len]?=?'\0'; ????} ????return?data_buf; }/*}}}*/ /** * Process the client request. * The client post data has stored in <code>r</code> */ static?void?p2s_urlquery_process_handler(ngx_http_request_t?*r) {/*{{{*/ ????printf(?"%s\n",?__PRETTY_FUNCTION__?); ????ngx_int_t rc?=?NGX_OK; ????ngx_buf_t?*b?=?NULL; ????ngx_chain_t out; ????ngx_http_p2s_conf_t?*conf?=?NULL; ????conf?=?(ngx_http_p2s_conf_t?*)ngx_http_get_module_loc_conf(r,?ngx_http_p2s_module); ????if?(conf?==?NULL) ????{ ????????ngx_http_finalize_request(r,?NGX_HTTP_INTERNAL_SERVER_ERROR); ????????return?; ????} ????struct?timeval?tv; ????gettimeofday(&tv,?NULL); ????size_t?bodylen?=?0; ????uint8_t*?contents?=?get_raw_http_body(?r,?&bodylen?); ????printf(?"time=%f http body data len=%d:\n%s\n",?(tv.tv_sec?+?tv.tv_usec/1000000.0f?),?(int)bodylen,?(char*)contents?); ????printf("----------------------http body data end-------------------\n"); ????/* Prepare for output, 128 is preserved for robust */ ????b?=?ngx_create_temp_buf(?r->pool,?128?+?conf->buflen?); ????if?(b?==?NULL) ????{ ????????ngx_http_finalize_request(r,?NGX_HTTP_INTERNAL_SERVER_ERROR); ????????return?; ????} ????out.buf?=?b; ????out.next?=?NULL; ????b->last?=?ngx_sprintf(b->pos,?"%s",?conf->ini_buf); ????r->headers_out.status?=?NGX_HTTP_OK; ????r->headers_out.content_length_n?=?b->last?-?b->pos; ????r->headers_out.content_type.len?=?sizeof("text/plain")?-?1; ????r->headers_out.content_type.data?=?(u_char?*)?"text/plain"; ????b->last_buf?=?1;/* there will be no more buffers in the request */ ????rc?=?ngx_http_send_header(r); ????if?(rc?==?NGX_ERROR?||?rc?>?NGX_OK?||?r->header_only) ????{ ????????ngx_http_finalize_request(r,?NGX_HTTP_INTERNAL_SERVER_ERROR); ????????return?; ????} ????ngx_http_output_filter(r,?&out); ????ngx_http_finalize_request(r,?0); }/*}}}*/ /** * Reading data handler * After read all the data from client we set a process handler */ static?ngx_int_t ngx_http_p2s_urlquery_handler(ngx_http_request_t?*r) {/*{{{*/ ????printf(?"%s\n",?__PRETTY_FUNCTION__?); ????ngx_int_t rc?=?NGX_DONE; ????rc?=?ngx_http_read_client_request_body(?r,?p2s_urlquery_process_handler?); ????if?(rc?>=?NGX_HTTP_SPECIAL_RESPONSE)?{ ????????return?rc; ????} ????return?NGX_DONE; }/*}}}*/ /** * set the request reading data handler */ static?char?* ngx_http_p2s_urlquery_set(?ngx_conf_t?*cf,?ngx_command_t?*cmd,?void?*conf?) {/*{{{*/ ????printf(?"%s\n",?__PRETTY_FUNCTION__?); ????ngx_http_core_loc_conf_t?*clcf; ????clcf?=?(ngx_http_core_loc_conf_t?*)ngx_http_conf_get_module_loc_conf(cf,?ngx_http_core_module); ????clcf->handler?=?ngx_http_p2s_urlquery_handler; ????return?NGX_CONF_OK; }/*}}}*/ static?void?* ngx_http_p2s_create_conf(ngx_conf_t?*cf) {/*{{{*/ ????printf(?"%s\n",?__PRETTY_FUNCTION__?); ????ngx_http_p2s_conf_t?*conf; ????conf?=?(ngx_http_p2s_conf_t?*)ngx_pcalloc(cf->pool,?sizeof(ngx_http_p2s_conf_t)); ????if?(conf?==?NULL)?{ ????????return?NGX_CONF_ERROR; ????} ????conf->consume?=?0; ????/* we open the nginx config file and send it back to client*/ ????FILE?*fp?=?fopen(?"../conf/nginx.conf",?"r"); ????if(?fp?==?NULL?) ????{ ????????return?NGX_CONF_ERROR; ????} ????fseek(fp,?0,?SEEK_END); ????long?len?=?ftell(?fp?); ????if?(?len?<?0?) ????{ ????????return?NGX_CONF_ERROR; ????} ????conf->buflen?=?(size_t)(len?+?1); ????conf->ini_buf?=?(char?*)ngx_palloc(?cf->pool,?len?+?1?); ????fseek(fp,?0,?SEEK_SET); ????fread(conf->ini_buf,?1,?len,?fp); ????conf->ini_buf[len]?=?0; ????fclose(fp); ????return?conf; }/*}}}*/
?
5. 編譯運行 現(xiàn)在可以編譯nginx和我們剛剛寫好的模塊了。
?
[zieckey@freebsd7.2 ~/nginx]$?cd [zieckey@freebsd7.2 ~]$?cd nginx/ [zieckey@freebsd7.2 ~/nginx]$?mkdir bininstalled [zieckey@freebsd7.2 ~/nginx]$?cd nginx-1.0.0 [zieckey@freebsd7.2 nginx-1.0.0]$?./configure?--add-module=/home/zieckey/nginx/module_dev_urlquery?--prefix=/home/zieckey/nginx/bininstalled ./configure:?error:?the HTTP rewrite module requires the PCRE library. You can either disable the module by using?--without-http_rewrite_module option,?or?install the PCRE library?into?the system,?or?build the PCRE library statically from the source with nginx by using?--with-pcre=<path>?option.
第一次錯誤,我們現(xiàn)在這個freebsd系統(tǒng)上沒有pcre庫,太悲催了,不過還好,這里給出了提示,說可以通過 --without-http_rewrite_module 來禁用使用pcre庫的 HTTP rewrite 模塊,我們試一試:?
[zieckey@freebsd7.2 nginx-1.0.0]$?./configure?--add-module=/home/zieckey/nginx/module_dev_urlquery?--prefix=/home/zieckey/nginx/bininstalled?--without-http_rewrite_module adding module?in?/home/zieckey/nginx/module_dev_urlquery +?ngx_http_p2s_module was configured
重點看到上面幾行信息,說明我們自己寫的模塊module_dev_urlquery已經(jīng)被nginx接納,生成makefile成功。?
[zieckey@freebsd7.2 nginx-1.0.0]$?make [zieckey@freebsd7.2 nginx-1.0.0]$?make install [zieckey@freebsd7.2 nginx-1.0.0]$?cd /home/zieckey/nginx/bininstalled/ [zieckey@freebsd7.2 bininstalled]$?ls conf html logs sbin [zieckey@freebsd7.2 bininstalled]$?cd conf [zieckey@freebsd7.2 conf]$?vim ngi nginx.conf nginx.conf.default? [zieckey@freebsd7.2 conf]$?vim nginx.conf
默認的配置文件是下面(將‘#’開頭的注釋行刪除之后)?
worker_processes 1; events { ????worker_connections 1024; }? http { ????include?mime.types; ????default_type application/octet-stream; ????sendfile?on; ????keepalive_timeout 65; ????server { ????????listen?80; ????????server_name localhost; ????????location?/ { ????????????root html; ????????????index index.html index.htm; ????????}? ???} }
我們在最上面添加如下選項:daemon off;? 可以讓程序不以daemon的方式運行,這樣我們可以看到一些調(diào)試的打印信息。 另外,在 server 里面添加一個 URI : location /urlquery { ??? p2s_urlquery; } 最后,我們修改下http監(jiān)聽的端口號,從默認的80改為8088,因為有些時候,我們并沒有權(quán)限在80端口上監(jiān)聽連接。 修改之后的配置文件全文如下:?
daemon?off; worker_processes 1; events { ????worker_connections 1024; } http { ????include?mime.types; ????default_type application/octet-stream; ????sendfile?on; ????keepalive_timeout 65; ????server { ????????listen?8088; ????????server_name localhost; ????????location?/ { ????????????root html; ????????????index index.html index.htm; ????????} ????????location?/urlquery { ????????????p2s_urlquery; ????????} ????} }
好了,到此為止,我們的所有工作就都準備好了,可以啟動nginx?
[zieckey@freebsd7.2 conf]$?cd /home/zieckey/nginx/bininstalled/sbin/ [zieckey@freebsd7.2 sbin]$?./nginx ngx_http_p2s_create_conf ngx_http_p2s_create_conf ngx_http_p2s_create_conf ngx_http_p2s_create_conf ngx_http_p2s_urlquery_set
新開一個終端,用curl來發(fā)起一個http post請求,post數(shù)據(jù)由-d參數(shù)指定:?
[zieckey@freebsd7.2 ~]$?curl?-d?"user=zieckey&verifykey=123456"?http://localhost:8088/urlquery daemon off; worker_processes 1; events { ????worker_connections 1024; } http { ????include?mime.types; ????default_type application/octet-stream; ????sendfile on; ????keepalive_timeout 65; ????server { ????????listen 8088; ????????server_name localhost; ????????location / { ????????????root html; ????????????index index.html index.htm; ????????????????} ????????????????location /urlquery { ????????????????????????p2s_urlquery; ????????????????} ????????} } [zieckey@freebsd7.2 ~]$
然后可以看看nginx服務器的一些輸出信息:?
[zieckey@freebsd7.2 sbin]$?./nginx ngx_http_p2s_create_conf ngx_http_p2s_create_conf ngx_http_p2s_create_conf ngx_http_p2s_create_conf ngx_http_p2s_urlquery_set ngx_http_p2s_urlquery_handler p2s_urlquery_process_handler get_raw_http_body time=1303552000.000000 http body data len=29: user=zieckey&verifykey=123456 ----------------------http body data end-------------------
?
6. 其他說明 6.1?配置文件和ngx_command_t的對應關(guān)系:
static ngx_command_t ngx_http_p2s_commands[]?= {/*{{{*/ ????{ ngx_string("p2s_urlquery"),?// 命令名,請對照 nginx.conf 看這個 ??????NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, ??????ngx_http_p2s_urlquery_set, ??????0, ??????0, ??????NULL }, ??????ngx_null_command };/*}}}*/ nginx.conf 中的 location 字段的配置是這樣的: ????????location /urlquery { ????????????p2s_urlquer; ????????}
?
這里的?/urlquery 是 URL 請求里的 URI 部分, 例如?http://localhost/urlquery?這條URL的請求會被這條配置項處理, 這條配置項,會去找命令名為“p2s_urlquery”的 ngx_command 去處理。
?
6.2 模塊名 代碼中的模塊變量名必須與config配置文件的名字一致 config 配置文件的內(nèi)容:ngx_addon_name=ngx_http_p2s_module 代碼中的內(nèi)容:
?
ngx_module_t ngx_http_p2s_module?=? {/*{{{*/ ????NGX_MODULE_V1, ????&ngx_http_p2s_module_ctx,?/*?module context?*/ ????ngx_http_p2s_commands,?/*?module directives?*/ ????NGX_HTTP_MODULE,?/*?module?type?*/ ????NULL,?/*?init master?*/ ????NULL,?/*?init module?*/ ????NULL,?/*?init process?*/ ????NULL,?/*?init thread?*/ ????NULL,?/*?exit thread?*/ ????NULL,?/*?exit process?*/ ????NULL,?/*?exit master?*/ ????NGX_MODULE_V1_PADDING };/*}}}*/
?
模塊的config配置文件會幫助 configure 生成一個ngx_modules.c文件,該文件里會引用?ngx_module_t? ngx_http_p2s_module 這個外部定義的變量,所以必須保持一致。在執(zhí)行 ./configure 完后,在nginx-1.0.0源碼的根目錄會多出來一個文件夾objs,在這里可以找到ngx_modules.c文件。 6.3 代碼調(diào)用關(guān)系 nginx程序啟動的時候,會去讀配置文件 conf/nginx.conf ,每讀到一個配置項,就會調(diào)用 module 注冊的回調(diào)函數(shù),所以這里可以看到nginx啟動的時候調(diào)用?ngx_http_p2s_create_conf 函數(shù)好幾次。 這個函數(shù)是由?
?
static ngx_http_module_t ngx_http_p2s_module_ctx?=? {/*{{{*/ ????NULL,?/*?preconfiguration?*/? ????NULL,?/*?postconfiguration?*/ ????NULL,?/*?create main configuration?*/ ????NULL,?/*?init main configuration?*/ ????NULL,?/*?create server configuration?*/ ????NULL,?/*?merge server configuration?*/ ????ngx_http_p2s_create_conf,?/*?create location configration?*/ ????NULL /*?merge location configration?*/ };/*}}}*/
指定的。 然后,在一個客戶端發(fā)起http請求的時候,例如我們這里的 “curl http://localhost:8088/urlquery” 命令實際上是發(fā)起一個 http 請求,URI 是 urlquery,所以,nginx 根據(jù)配置文件的配置項,找到??urlquery 對應的處理模塊名?p2s_urlquery, 然后調(diào)用 p2s_urlquery 這個名字關(guān)聯(lián)的?ngx_http_p2s_urlquery_set 回調(diào)函數(shù)。 ngx_http_p2s_urlquery_set?回調(diào)函數(shù)又會設置一個?ngx_http_p2s_urlquery_handler 回調(diào)函數(shù),ngx_http_p2s_urlquery_handler 回調(diào)函數(shù)會在 nginx 讀取客戶端發(fā)過來的http數(shù)據(jù)的時候被調(diào)用。 ngx_http_p2s_urlquery_handler 又會設置一個?p2s_urlquery_process_handler 回調(diào)函數(shù), p2s_urlquery_process_handler 會在?nginx 讀取完客戶端發(fā)過來的http數(shù)據(jù)之后的時候被調(diào)用, 不難發(fā)現(xiàn),p2s_urlquery_process_handler函數(shù)是我們真正的處理邏輯,因為這個時候已經(jīng)收完了客戶端的http數(shù)據(jù)。 p2s_urlquery_process_handler 函數(shù)先調(diào)用?get_raw_http_body 這個我們自己封裝的函數(shù)將客戶端發(fā)送過來的 http data 讀取到一個緩沖區(qū)中,然后處理(這里我們只是簡單的printf)。然后,我們準備好數(shù)據(jù),發(fā)送會客戶端。
到此,我們完成了一個很簡單的模塊的開發(fā)和調(diào)試工作,也不是那么困難。 同時對一些函數(shù)調(diào)用,配置文件關(guān)系等等比較含糊的地方做了詳細說明。
總結(jié)
以上是生活随笔 為你收集整理的Nginx 模块开发(1)—— 一个稍稍能说明问题模块开发 Step By Step 过程 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。