I/O函數(shù)包
FastCGI軟件開(kāi)發(fā)套件,開(kāi)源的WebServer 2.0服務(wù)器包含I/O函數(shù)包用與簡(jiǎn)化把已存在的CGI程序轉(zhuǎn)成FastCGI程序或者編寫(xiě)FastCGI程序,在開(kāi)發(fā)套件中有兩個(gè)函數(shù)包:fcgi_stdio 和 fcgiapp,在你的程序中必須包含這些包中的一個(gè):
fcgi_stdio.h fcgiapp.h fcgi_stdio包,是fcgiapp包的頂層包,在轉(zhuǎn)化CGI程序或者是寫(xiě)新的FastCGI程序是,我們強(qiáng)烈推薦你用它,fcgi_stdio包有以下幾個(gè)優(yōu)點(diǎn):
簡(jiǎn)單:只要有三個(gè)性的API需要學(xué)。
易懂:如果你正包CGI程序轉(zhuǎn)化為FastCGI程序,你會(huì)發(fā)現(xiàn)CGI程序與FastCGI程序之間只有很少的區(qū)別。在我們?cè)O(shè)計(jì)函數(shù)庫(kù)的時(shí)候我們盡可能的 把FastCGI應(yīng)用程序變得容易理解,以至于我們?cè)诮⑿翭astCGI程序的時(shí)候我們使用相同的環(huán)境變量,相同的解析查詢(xún)字符串的技術(shù),以及相同的 I/O程序等。
方便:這個(gè)庫(kù)函數(shù)提供了CGI和FastCGI二進(jìn)制的文件的完美兼容。因此不管是CGI還是FastCGI,都同樣運(yùn)行。
代碼結(jié)構(gòu)
FastCGI的代碼構(gòu)成,把你的代碼分成兩個(gè)獨(dú)立部分:
1.初始化部分:只執(zhí)行一次
2.應(yīng)答循環(huán)部分:FastCGI腳本每被調(diào)用一次,這部分九被執(zhí)行一次
一個(gè)應(yīng)答循環(huán)的典型格式如下:
while (FCGI_Accept() >= 0) {//循環(huán)條件
# 應(yīng)答循環(huán)體
}
知道一個(gè)客戶(hù)端請(qǐng)求來(lái)的時(shí)候FCGI_Accept塊才執(zhí)行,并返回0。如果有一個(gè)系統(tǒng)故障,或是系統(tǒng)管理員終止進(jìn)程,Accept將返回-1。
如果應(yīng)用程序作為一個(gè)CGI程序被調(diào)用,那么第一次調(diào)用Accept時(shí),返回0,第二次總是返回-1,產(chǎn)生CGI行為。(請(qǐng)?jiān)斠?jiàn)20頁(yè)的"FCGI_Accept (3)" )
注意,在CGI中鼓勵(lì)用小腳本,然而在FastCGI中則鼓勵(lì)使用組合式的腳本。你可以在從新構(gòu)想你的程序的全局結(jié)構(gòu),來(lái)獲得FastCGI的高性能。
例1: TinyFastCGI
這是一個(gè)用C語(yǔ)言寫(xiě)的一個(gè)簡(jiǎn)單FastCGI應(yīng)答程序例子:
#include "fcgi_stdio.h"
#include
int count;
void initialize(void)
{
count=0;
}
void main(void)
{
initialize();
while (FCGI_Accept() >= 0) {
printf("Content-type: text/html\r\n"
"\r\n"
""
"
FastCGI Hello! (C, fcgi_stdio library)
"
"Request number %d running on host %s\n",
++count, getenv("SERVER_HOSTNAME"));
}
}
例2:原始數(shù)據(jù)產(chǎn)生器
思考一下,一個(gè)應(yīng)答應(yīng)用程序產(chǎn)生第N次原始數(shù)據(jù)。
一個(gè)CGI應(yīng)用程序?qū)](méi)有有效的方法來(lái)解決這個(gè)問(wèn)題。例如,如果用戶(hù)訪(fǎng)問(wèn)第50000次的原始數(shù)據(jù),那么CGI應(yīng)用程序就不許從第一條原始數(shù)據(jù)開(kāi)始計(jì)算,知道第50000條的,要是應(yīng)用程序終止,伴隨著她辛苦積累的數(shù)據(jù)也會(huì)隨之消失。
如果一個(gè)客戶(hù)端想訪(fǎng)問(wèn)第4900條原始數(shù)據(jù),那么服務(wù)器必須重新開(kāi)始積累。
由于我們能維持這個(gè)狀態(tài),F(xiàn)astCGI應(yīng)用程序?qū)εc這樣的問(wèn)題就更有效。一個(gè)FastCGI應(yīng)用程序在初始化階段能夠計(jì)算一個(gè)擴(kuò)展的源數(shù)據(jù)的表,并保持表的不同范圍。當(dāng)客戶(hù)端請(qǐng)求一個(gè)特別原始數(shù)據(jù)的時(shí)候,循環(huán)應(yīng)答需要從表里查詢(xún)。
這里有一個(gè)原始數(shù)據(jù)代碼事例:
#include "fcgi_stdio.h"
#include
#include
#define POTENTIALLY_PRIME 0
#define COMPOSITE 1
#define VALS_IN_SIEVE_TABLE 1000000
#define MAX_NUMBER_OF_PRIME_NUMBERS 78600
long int sieve_table[VALS_IN_SIEVE_TABLE];
long int prime_table[MAX_NUMBER_OF_PRIME_NUMBERS];
void
initialize_prime_table(void)
{
long int prime_counter=1;
long int current_prime=2, c, d;
prime_table[prime_counter]=current_prime;
while (current_prime < VALS_IN_SIEVE_TABLE) {
for (c = current_prime; c <= VALS_IN_SIEVE_TABLE;
c += current_prime) {
sieve_table[c] = COMPOSITE;
}
for (d=current_prime+1; sieve_table[d] == COMPOSITE; d++);
prime_table[++prime_counter]=d;
current_prime=d;
}
}
void main(void)
{
char *query_string;
long int n;
initialize_prime_table();
while(FCGI_Accept() >= 0) {
printf("Content-type: text/html\r\n"
"\r\n");
printf("\n"
"
Prime FastCGI
\n");
query_string = getenv("QUERY_STRING");
if(query_string == NULL) {
printf("Usage: Specify a positive number in the query string.\n");
} else {
query_string = strchr(query_string, `=') + 1;
n = strtol(query_string);
if(n < 1) {
printf("The query string `%s' is not a positive number.\n",
query_string);
} else if(n > MAX_NUMBER_OF_PRIME_NUMBERS) {
printf("The number %d is too large for this program.\n", n);
} else{
printf("The %ldth prime number is %ld.\n", n, prime_table[n]);
}
}
}
}
這個(gè)應(yīng)用程序在初始化時(shí)有一個(gè)顯而意見(jiàn)的開(kāi)銷(xiāo),但是后來(lái)的訪(fǎng)問(wèn)是快速的。