日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Nginx >内容正文

Nginx

Nginx + CGI/FastCGI + C/Cpp

發(fā)布時間:2025/7/14 Nginx 87 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Nginx + CGI/FastCGI + C/Cpp 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

http://www.cnblogs.com/skynet/p/4173450.html

Nginx + CGI/FastCGI + C/Cpp

2014-12-19 11:05 by 吳秦,?19794?閱讀,?6?評論,?收藏,?編輯

接著上篇《Nginx安裝與使用》,本篇介紹CGI/FASTCGI的原理、及如何使用C/C++編寫簡單的CGI/FastCGI,最后將CGI/FASTCGI部署到nginx。內(nèi)容大綱如下:

1.?????CGI

1.1.?????環(huán)境變量

1.2.?????標準輸入

2.?????FastCGI

3. nginx cgi/fastcgi

3.1. nginx + fastcgi

3.1.1. spawn-fcgi

3.1.2.?編寫fastcgi應用程序

3.1.3. nginx fastcgi配置

3.2. nginx + cgi

3.2.1 fastcgi-wrapper

3.2.2. nginx?fcgiwrap配置

3.2.3.?編寫cgi應用程序

參考鏈接

?

1.CGI

通用網(wǎng)關(guān)接口Common?Gateway?Interface/CGI描述了客戶端和服務器程序之間傳輸數(shù)據(jù)的一種標準,可以讓一個客戶端,從網(wǎng)頁瀏覽器向執(zhí)行在網(wǎng)絡(luò)服務器上的程序請求數(shù)據(jù)。CGI?獨立于任何語言的,CGI?程序可以用任何腳本語言或者是完全獨立編程語言實現(xiàn),只要這個語言可以在這個系統(tǒng)上運行。Unix shell?script,?Python,?Ruby,?PHP, perl,?Tcl,?C/C++,和?Visual Basic?都可以用來編寫?CGI?程序。(http://www.dwz.cn/yFFgQ)

最初,CGI?是在?1993?年由美國國家超級電腦應用中心(NCSA)為?NCSA HTTPd?Web?服務器開發(fā)的。這個?Web?服務器使用了?UNIX?shell?環(huán)境變量?來保存從?Web?服務器傳遞出去的參數(shù),然后生成一個運行?CGI?的獨立的進程。cgi的處理流程如下圖所示:

?

l???step1.?web?服務器收到客戶端(瀏覽器)的請求Http Request,啟動CGI程序,并通過環(huán)境變量標準輸入傳遞數(shù)據(jù)

l???step2. cgi進程啟動解析器、加載配置(如業(yè)務相關(guān)配置)、連接其它服務器(如數(shù)據(jù)庫服務器)、邏輯處理等

l???step3. cgi程將處理結(jié)果通過標準輸出標準錯誤,傳遞給web?服務器

l???step4. web?服務器收到cgi返回的結(jié)果,構(gòu)建Http Response返回給客戶端,并殺死cgi進程

web服務器與cgi通過環(huán)境變量、標準輸入、標準輸出、標準錯誤互相傳遞數(shù)據(jù)。

1.1.環(huán)境變量

GET請求,它將數(shù)據(jù)打包放置在環(huán)境變量QUERY_STRING中,CGI從環(huán)境變量QUERY_STRING中獲取數(shù)據(jù)。常見的環(huán)境變量如下表所示:

環(huán)境變數(shù)

內(nèi)容

AUTH_TYPE

存取認證類型。

CONTENT_LENGTH

由標準輸入傳遞給CGI程序的數(shù)據(jù)長度,以bytes或字元數(shù)來計算。

CONTENT_TYPE

請求的MIME類型。

GATEWAY_INTERFACE

服務器的CGI版本編號。

HTTP_ACCEPT

瀏覽器能直接接收的Content-types,?可以有HTTP Accept header定義.

HTTP_USER_AGENT

遞交表單的瀏覽器的名稱、版本?和其他平臺性的附加信息。

HTTP_REFERER

遞交表單的文本的?URL,不是所有的瀏覽器都發(fā)出這個信息,不要依賴它

PATH_INFO

傳遞給cgi程式的路徑信息。

QUERY_STRING

傳遞給CGI程式的請求參數(shù),也就是用"?"隔開,添加在URL后面的字串。

REMOTE_ADDR

client端的host名稱。

REMOTE_HOST

client端的IP位址。

REMOTE_USER

client端送出來的使用者名稱。

REMOTE_METHOD

client端發(fā)出請求的方法(如get、post)。

SCRIPT_NAME

CGI程式所在的虛擬路徑,如/cgi-bin/echo。

SERVER_NAME

server的host名稱或IP地址。

SERVER_PORT

收到request的server端口。

SERVER_PROTOCOL

所使用的通訊協(xié)定和版本編號。

SERVER_SOFTWARE

server程序的名稱和版本。

1.2.標準輸入

環(huán)境變量的大小是有一定的限制的,當需要傳送的數(shù)據(jù)量大時,儲存環(huán)境變量的空間可能會不足,造成數(shù)據(jù)接收不完全,甚至無法執(zhí)行CGI程序。因此后來又發(fā)展出另外一種方法:POST,也就是利用I/O重新導向的技巧,讓CGI程序可以由STDIN和STDOUT直接跟瀏覽器溝通。 當我們指定用這種方法傳遞請求的數(shù)據(jù)時,web 服務器收到數(shù)據(jù)后會先放在一塊輸入緩沖區(qū)中,并且將數(shù)據(jù)的大小記錄在CONTENT_LENGTH這個環(huán)境變數(shù),然后調(diào)用CGI程式并將CGI程序的STDIN指向這塊緩沖區(qū),于是我們就可以很順利的通過STDIN和環(huán)境變數(shù)CONTENT_LENGTH得到所有的資料,再沒有資料大小的限制了。 ?

總結(jié):CGI使外部程序與Web服務器之間交互成為可能。CGI程式運行在獨立的進程中,并對每個Web請求建立一個進程,這種方法非常容易實現(xiàn),但效率很差,難以擴展。面對大量請求,進程的大量建立和消亡使操作系統(tǒng)性能大大下降。此外,由于地址空間無法共享,也限制了資源重用。

2.FastCGI

快速通用網(wǎng)關(guān)接口(Fast Common Gateway Interface/FastCGI)是通用網(wǎng)關(guān)接口(CGI)的改進,描述了客戶端和服務器程序之間傳輸數(shù)據(jù)的一種標準。FastCGI致力于減少Web服務器CGI程式之間互動的開銷,從而使服務器可以同時處理更多的Web請求。與為每個請求創(chuàng)建一個新的進程不同,FastCGI使用持續(xù)的進程來處理一連串的請求。這些進程由FastCGI進程管理器管理,而不是web服務器。(http://www.dwz.cn/yFMap)

?

當進來一個請求時,Web?服務器把環(huán)境變量和這個頁面請求通過一個unix domain socket(都位于同一物理服務器)或者一個IP Socket(FastCGI部署在其它物理服務器)傳遞給FastCGI進程。

?

l??step1. Web?服務器啟動時載入初始化FastCGI執(zhí)行環(huán)境?。?例如IIS ISAPI、apache mod_fastcgi、nginx ngx_http_fastcgi_module、lighttpd mod_fastcgi

l??step2. FastCGI進程管理器自身初始化,啟動多個CGI解釋器進程并等待來自Web?服務器的連接。啟動FastCGI進程時,可以配置以ip和UNIX?域socket兩種方式啟動。?

l??step3.?當客戶端請求到達Web?服務器時,?Web?服務器將請求采用socket方式轉(zhuǎn)發(fā)到?FastCGI主進程,FastCGI主進程選擇并連接到一個CGI解釋器。Web?服務器將CGI環(huán)境變量和標準輸入發(fā)送到FastCGI子進程。

l??step4. FastCGI子進程完成處理后將標準輸出和錯誤信息從同一socket連接返回Web?服務器。當FastCGI子進程關(guān)閉連接時,請求便處理完成。

l??step5. FastCGI子進程接著等待并處理來自Web?服務器的下一個連接。

由于?FastCGI?程序并不需要不斷的產(chǎn)生新進程,可以大大降低服務器的壓力并且產(chǎn)生較高的應用效率。它的速度效率最少要比CGI?技術(shù)提高?5?倍以上。它還支持分布式的部署,?即?FastCGI程序可以在web?服務器以外的主機上執(zhí)行。

總結(jié):CGI?就是所謂的短生存期應用程序,FastCGI?就是所謂的長生存期應用程序。FastCGI像是一個常駐(long-live)型的CGI,它可以一直執(zhí)行著,不會每次都要花費時間去fork一次(這是CGI最為人詬病的fork-and-execute?模式)。

3.nginx cgi/fastcgi

nginx?不能像apache那樣直接執(zhí)行外部可執(zhí)行程序,但nginx可以作為代理服務器,將請求轉(zhuǎn)發(fā)給后端服務器,這也是nginx的主要作用之一。其中nginx就支持FastCGI代理,接收客戶端的請求,然后將請求轉(zhuǎn)發(fā)給后端fastcgi進程。下面介紹如何使用C/C++編寫cgi/fastcgi,并部署到nginx中。

3.1.?nginx + fastcgi

通過前面的介紹知道,fastcgi進程由FastCGI進程管理器管理,而不是nginx。這樣就需要一個FastCGI管理,管理我們編寫fastcgi程序。本文使用spawn-fcgi作為FastCGI進程管理器。

3.1.1.?spawn-fcgi

spawn-fcgi是一個通用的FastCGI進程管理器,簡單小巧,原先是屬于lighttpd的一部分,后來由于使用比較廣泛,所以就遷移出來作為獨立項目了。spawn-fcgi使用pre-fork?模型,功能主要是打開監(jiān)聽端口,綁定地址,然后fork-and-exec創(chuàng)建我們編寫的fastcgi應用程序進程,退出完成工作。fastcgi應用程序初始化,然后進入死循環(huán)偵聽socket的連接請求。

安裝spawn-fcgi:

l??獲取spawn-fcgi編譯安裝包,在http://redmine.lighttpd.net/projects/spawn-fcgi/wiki上可以獲取當前最新的版本。

l??解壓縮spawn-fcgi-x.x.x.tar.gz包。

l??進入解壓縮目錄,執(zhí)行./configure。

l??make & make install

如果遇到以下錯誤:“?./autogen.sh: x: autoreconf: not found”,因為沒有安裝automake?工具,ubuntu用下面的命令安裝好就可以了:sudo apt-get install autoconf automake libtool?。

spawn-fcgi的幫助信息可以通過man spawn-fcgi或spawn-fcgi?–h獲得,下面是部分常用spawn-fcgi參數(shù)信息:

-f <fcgiapp>?指定調(diào)用FastCGI的進程的執(zhí)行程序位置

-a <addr>?綁定到地址addr。

-p <port>?綁定到端口port。

-s <path>?綁定到unix domain socket

-C <childs>?指定產(chǎn)生的FastCGI的進程數(shù),默認為5。(僅用于PHP)

-P <path>?指定產(chǎn)生的進程的PID文件路徑。

-F <childs>?指定產(chǎn)生的FastCGI的進程數(shù)(C的CGI用這個)

-u和-g FastCGI使用什么身份(-u?用戶?-g?用戶組)運行,CentOS下可以使用apache用戶,其他的根據(jù)情況配置,如nobody、www-data等。

3.1.2.?編寫fastcgi應用程序

使用C/C++編寫fastcgi應用程序,可以使用FastCGI軟件開發(fā)套件或者其它開發(fā)框架,如fastcgi++。

本文使用FastCGI軟件開發(fā)套件——fcgi(http://www.fastcgi.com/drupal/node/6?q=node/21),通過此套件可以輕松編寫fastcgi應用程序,安裝fcgi:

l??獲取fcgi編譯安裝包,在http://www.fastcgi.com/drupal/node/5上可以獲取當前最新的版本。

l??解壓縮fcgi-x.x.x.tar.gz包。

l??進入解壓縮目錄,執(zhí)行./configure。

l??make & make install

如果編譯提示一下錯誤:

fcgio.cpp: In destructor 'virtual fcgi_streambuf::~fcgi_streambuf()':

fcgio.cpp:50: error: 'EOF' was not declared in this scope
fcgio.cpp: In member function 'virtual int fcgi_streambuf::overflow(int)':
fcgio.cpp:70: error: 'EOF' was not declared in this scope
fcgio.cpp:75: error: 'EOF' was not declared in this scope
fcgio.cpp: In member function 'virtual int fcgi_streambuf::sync()':
fcgio.cpp:86: error: 'EOF' was not declared in this scope
fcgio.cpp:87: error: 'EOF' was not declared in this scope
fcgio.cpp: In member function 'virtual int fcgi_streambuf::underflow()':
fcgio.cpp:113: error: 'EOF' was not declared in this scope
make[2]: *** [fcgio.lo] Error 1
make[2]: Leaving directory `/root/downloads/fcgi-2.4.1-SNAP-0910052249/libfcgi'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/root/downloads/fcgi-2.4.1-SNAP-0910052249'

make: *** [all] Error 2

解決辦法:在/include/fcgio.h文件中加上?#include <cstdio>,然后再編譯安裝就通過了。

如果提示找不到動態(tài)庫,請在LD_LIBRARY_PATH或/etc/ld.so.conf中添加fcgi的安裝路徑,如/usr/local/lib,并執(zhí)行l(wèi)dconfig更新一下。

#include?"fcgi_stdio.h"

#include?<stdlib.h>

?

int?main(void)

{

????int?count?= 0;

????while?(FCGI_Accept() >= 0)

????????printf("Content-type: text/html\r\n"

????????"\r\n"

????????"<title>FastCGI Hello!</title>"

????????"<h1>FastCGI Hello!</h1>"

????????"Request number %d running on host <i>%s</i>\n",

????????++count,?getenv("SERVER_NAME"));

????return?0;

} ?

編譯g++ main.cpp -o demo –lfcgi,并將demo部署到/opt/nginx-1.7.7/cgi-bin/目錄

通過spawn-fcgi啟動c/c++編寫好的fastcgi程序:/opt/nginx-1.7.7/sbin/spawn-fcgi -a 127.0.0.1 -p 8081 -f /opt/nginx-1.7.7/cgi-bin/demo?

3.1.3.?nginx fastcgi配置

關(guān)于nginx的幾個配置文件解析,可以參閱《Nginx安裝與使用》http://www.cnblogs.com/skynet/p/4146083.html,在上篇的nginx.conf基礎(chǔ)上增加下面的fastcgi配置。

?

這樣nginx收到http://localhost/demo.cgi請求時,會匹配到location = /demo.cgi塊,將請求傳到后端的fastcgi應用程序處理。如下如所示:(注意其中number為80,是因為我請求了80次)

?

3.2.?nginx + cgi

nginx?不能直接執(zhí)行外部可執(zhí)行程序,并且cgi是接收到請求時才會啟動cgi進程,不像fastcgi會在一開就啟動好,這樣nginx天生是不支持?cgi?的。nginx?雖然不支持cgi,但它支持fastCGI。所以,我們可以考慮使用fastcgi包裝來支持?cgi。原理大致如下圖所示:pre-fork幾個通用的代理fastcgi程序——fastcgi-wrapper,fastcgi-wrapper啟動執(zhí)行cgi然后將cgi的執(zhí)行結(jié)果返回給nginx(fork-and-exec)。

?

明白原理之后,編寫一個fastcgi-warpper也比較簡單。網(wǎng)上流傳比較多的一個解決方案是,來自nginx wiki(http://wiki.nginx.org/SimpleCGI)上的使用perl的fastcgi包裝腳本cgiwrap-fcgi.pl。但我對perl不是很感冒,下面給出一個C/C++寫的fastcgi-wrapper。

3.2.1.?fastcgi-wrapper

其實編寫C/C++的fastcgi-wrapper,就是寫一個C/C++的fastcgi,步驟和原理跟前面的小節(jié)(nginx+fastcgi)一樣。github上已經(jīng)有人開源了,C寫的fastcgi-wrapper:https://github.com/gnosek/fcgiwrap。

安裝fcgiwrap:

l??下載(https://github.com/gnosek/fcgiwrap.git)

l??解壓縮fcgiwrap,進入解壓目錄

l??autoreconf -i

l??./configure

l??make && make install

啟動fastcgi-wrapper:/opt/nginx-1.7.7/sbin/spawn-fcgi?-f /usr/local/sbin/fcgiwrap -p 8081

3.2.2.?nginx?fcgiwrap配置

在nginx.conf中增加下面的loaction配置塊,這樣所有的xxx.cgi請求都會走到fcgiwrap,然后fcgiwrap會執(zhí)行cgi-bin目錄下的cgi程序。

?

?

3.2.3.?編寫cgi應用程序

?

#include?<stdio.h>

#include?<stdlib.h>

?

int?main(void)

{

????int?count?= 0;

????printf("Content-type: text/html\r\n"

????????"\r\n"

????????"<title>CGI Hello!</title>"

?

????????"<h1>CGI Hello!</h1>"

????????"Request number %d running on host <i>%s</i>\n",

????????++count,?getenv("SERVER_NAME"));

????return?0;

}

?

tyler@ubuntu:~/ClionProjects/HelloFastCGI$ g++ cgi.cpp -o cgidemo -lfcgi

tyler@ubuntu:~/ClionProjects/HelloFastCGI$ sudo cp cgidemo /opt/nginx-1.7.7/cgi-bin/

?

?

注意圖中的請求次數(shù)一直都是1,因為cgi的模式是fork-and-exec,每次都是一個新的進程。

?

?

?

總結(jié)

以上是生活随笔為你收集整理的Nginx + CGI/FastCGI + C/Cpp的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。