3. 撰写 FastCGI 应用程序
撰写全新的 FastCGI 应用程序,或是将旧有的 CGI 程序改写成 FastCGI 应用程序都非常的简单,只要使用 fcgi-devkit 所附的 fcgi_stdio 函式库即可。
基本上,fcgi_stdio 函式库已被
设计成让开发人员撰写 FastCGI 应用程序就像写一般 CGI 程序一样,同时做到程序保有和 CGI 最大的兼容度,又能享受到 FastCGI 所带来的优点。使用 fcgi_stdio 函式库的另一项好处是,编译出来的执行档可同时以 CGI 以及 FastCGI 的方式执行。
3.1 程序架构
对 CGI 程序而言,其生命期就是从一个联机请求 (request) 开始到联机结束。而 FastCGI 程序就像是比较『长命』的 CGI 程序,其生命期横跨不同的联机请求,可从 Web
服务器激活开始到 Web 服务器停止。
由于 FastCGI 程序长命的特性,它和一般 CGI 程序主要的差异就在于把初始化 (initialization) 的部份和处理联机请求的部份区分开来,程序的架构如下所示:
Initialization Code
Start of response loop
body of response loop
End of response loop
Initialization Code 的部份只会在 FastCGI 程序激活时执行一次,程序初始化的部份像是
内存的配置,建立和
数据库的联机等都可以写在这里。
而 Start of response loop 到 End of response loop 之间的程序在每次发生联机请求时就会执行,这部份的程序才是真正处理每次联机请求要做的事情。例如接受使用者输入的参数,从数据库取出资料,执行运算动作,回复结果给使用者等等。
一个简单的 FastCGI 程序如下 (tiny-fcgi.c)
#include "fcgi_stdio.h"
#include <stdlib.h>
void main(void)
{
/* Initialization Code */
int count = 0;
/* Start of response loop */
while(FCGI_Accept() >= 0) {
/* body of response loop */
printf("Content-type: text/html\r\n"
"\r\n"
"<title>FastCGI Hello! (C, fcgi_stdio library)</title>"
"<h1>FastCGI Hello! (C, fcgi_stdio library)</h1>"
"Request number %d running on host <i>%s</i> "
"Process ID: %d\n",
++count, getenv("SERVER_NAME"), getpid());
}
/* End of response loop */
}
3.2 引入 fcgi_stdio.h 标头档
开始撰写一个新的 FastCGI 应用程序时,必须引入 fcgi_stdio.h 这个标头档:
#include ``fcgi_stdio.h''
如果要改写旧有的 CGI 程序成 FastCGI 程序,请把原本引入 stdio.h 的部份换掉:
#ifndef FASTCGI
#include <stdio.h>
#else
#include ``fcgi_stdio.h''
#endif
上面的写法是利用 C 的前置编译器做处理,如果在编译时加入 -DFASTCGI 的参数则引入 fcgi_stdio.h ,反之则否。假设我们把 fcgi_stdio.h 标头文件放在 /usr/local/include/fastcgi 这个目录下的话,为了在编译时引入 fcgi_stdio.h 标头档,请加入 -I/usr/local/include/fastcgi 的参数。
$ cc -I/usr/local/include/fastcgi -c program.c
注意
如果你的程序使用到其它的函式库,请务必检查这些函式库是否有使用到 stdio.h 这个档,如果有的话必须一并换成 fcgi_stdio.h。举例来说,假如你的程序用到 GD 函式库4来产生 GIF 图形,请记得把 gd.h 中引入 stdio.h 的部份换成 fcgi_stdio.h,否则遇到 IO 的函式时会发生错误 (Core Dump)。
3.3 FastCGI 处理循环
在 FastCGI 程序中负责处理联机请求的程序,必须用一个 while 循环包起来,利用 fcgi_stdio 函式库中的 FCGI_Accept() 函式库来判断是否有新的联机请求发生。
FastCGI 程序被激活后,首先进行初始化的动作,如变量宣告、内存配置、或是与数据库建立联机等。执行到 FCGI_Accept() 时程序就会暂停,等到当某一个联机请求发生时,FCGI_Accept() 会传回大于零的值,程序即刻进入循环的主体,可能是执行 SQL 指令,运算
9
7
3
1
2
4
8
: