用C语言开发FastCGI应用程序——fcgi_stdio包API

来源:互联网 发布:淘宝格拾子湖铺 编辑:程序博客网 时间:2024/05/11 20:37

官方文档:http://www.fastcgi.com/devkit/doc/fcgi-devel-kit.htm

官网头文件:http://www.fastcgi.com/devkit/include/fcgi_stdio.h

简介

FastCGI软件开发套件用于简化把现有的CGI程序转成FastCGI程序或者编写FastCGI程序。

  I/O函数包

  在开发套件中有两个函数包:fcgi_stdio 和 fcgiapp,在你的程序中必须包含这些包中的一个:

  fcgi_stdio.h fcgiapp.h 

        fcgi_stdio包,是fcgiapp包的顶层包,在转化CGI程序或者是写新的FastCGI程序是,我们强烈推荐你用它。用这个库,你的二进制程序既可以当作CGI也可以当作FASTCGI程序来运行(原文:Thefcgi_stdio library provides the easiest transition for C CGI programs and C CGI programmers to FastCGI. Using this library your application can run using either CGI or FastCGI, with the same binary for both situations.)。

        fcgiapp包是另一个fastcgi库。它没有像fcgi_stdio包一样提供那么多兼容性;所以,它也没有使用那么多宏。fcgi_stdio包是运行在fcgiapp上的一层。

                基于fcgiapp包运行的程序不能当作CGI程序来运行。这种特性只在fcgi_stdio层提供。

                fcgiapp包中的函数以 FCGX_ 开头,而不是以 FCGI_ 开头。比如:FCGX_Accept 是 FCGI_Accept 的fcgiapp版本。

                fcgiapp包中的函数的描述文档以扩展的注释方式包括在头文件include/fcgiapp.h 中。范例程序examples/tiny-fcgi2.c 和examples/echo2.c 说明如果使用fcgiapp包。

        (原文:

The fcgiapp library is a second C library for FastCGI. It does not provide the high degree of source code compatibility provided byfcgi_stdio; in return, it does not make such heavy use of#define.fcgi_stdio is implemented as a thin layer on top of fcgiapp.

Applications built using the fcgiapp library cannot run as CGI programs; that feature is provided at thefcgi_stdio level.

Functions defined in fcgiapp are named using the prefix FCGX_ rather thanFCGI_. For instance,FCGX_Accept is thefcgiapp version ofFCGI_Accept.

Documentation of the fcgiapp library takes the form of extensive comments in the header fileinclude/fcgiapp.h. The sample programsexamples/tiny-fcgi2.c andexamples/echo2.c illustrate how to usefcgiapp.)

        本文主要介绍fcgi_stdio包,它有以下几个优点:

  简单:只要有三个新的API需要学。

  易懂:如果你正把CGI程序转化为FastCGI程序,你会发现CGI程序与FastCGI程序之间只有很少的区别。在我们设计函数库的时候我们尽可能的 把FastCGI应用程序变得容易理解,以至于我们在建立新FastCGI程序的时候我们使用相同的环境变量,相同的解析查询字符串的技术,以及相同的 I/O程序等。

  方便:这个库函数提供了CGI和FastCGI二进制的文件的完美兼容。因此不管是CGI还是FastCGI,都同样运行。

  fcgi_stdio包开发的fastcgi代码结构

  FastCGI的代码构成,把你的代码分成两个独立部分:

  1.初始化部分:只执行一次

  2.应答循环部分:FastCGI脚本每被调用一次,这部分就被执行一次

  

  一个应答循环的典型格式如下:

  while (FCGI_Accept() >= 0) {//循环条件

  # 应答循环体

  }

  

  直到一个客户端请求来的时候FCGI_Accept块才执行,并返回0。如果有一个系统故障,或是系统管理员终止进程,Accept将返回-1。

  如果应用程序作为一个CGI程序被调用,那么第一次调用Accept时,返回0,第二次总是返回-1,产生CGI行为。(请详见20页的"FCGI_Accept (3)" )

  注意,在CGI中鼓励用小脚本,然而在FastCGI中则鼓励使用组合式的脚本。你可以在重新构想你的程序的全局结构,来获得FastCGI的高性能。

  例1: TinyFastCGI

  这是一个用C语言写的一个简单FastCGI应答程序例子:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include "fcgi_stdio.h"  
  2. #include <stdlib.h>  
  3.   
  4. int count;  
  5.   
  6. void initialize(void)  
  7. {  
  8.     count=0;  
  9. }  
  10. void main(void)  
  11. {  
  12.     initialize();  
  13.     while (FCGI_Accept() >= 0)  
  14.     {  
  15.         printf( "Content-type: text/html\r\n"  
  16.             "\r\n"  
  17.             "<title>FastCGI Hello! (C, fcgi_stdio library)</title>"  
  18.             "<h1>FastCGI Hello! (C, fcgi_stdio library)</h1>"  
  19.             "Request number %d running on host <i>%s</i>\n",  
  20.             ++ count, getenv( "SERVER_HOSTNAME" ) );  
  21.   }  
  22. }  

  例2:原始数据产生器

  思考一下,一个应答应用程序产生第N次原始数据。

  一个CGI应用程序将没有有效的方法来解决这个问题。例如,如果用户访问第50000次的原始数据,那么CGI应用程序就不许从第一条原始数据开始计算,直到第50000条的,要是应用程序终止,伴随着她辛苦积累的数据也会随之消失。

  如果一个客户端想访问第4900条原始数据,那么服务器必须重新开始积累。

  由于我们能维持这个状态,FastCGI应用程序对与这样的问题就更有效。一个FastCGI应用程序在初始化阶段能够计算一个扩展的源数据的表,并保持表的不同范围。当客户端请求一个特别原始数据的时候,循环应答需要从表里查询。

  这里有一个原始数据代码事例:

  

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include "fcgi_stdio.h"  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4.   
  5. #define POTENTIALLY_PRIME 0  
  6. #define COMPOSITE 1  
  7. #define VALS_IN_SIEVE_TABLE 1000000  
  8. #define MAX_NUMBER_OF_PRIME_NUMBERS 78600  
  9.   
  10. long int sieve_table[VALS_IN_SIEVE_TABLE];  
  11. long int prime_table[MAX_NUMBER_OF_PRIME_NUMBERS];  
  12.   
  13. void initialize_prime_table(void)  
  14. {  
  15.     long int prime_counter = 1;  
  16.     long int current_prime = 2, c, d;  
  17.       
  18.     prime_table[prime_counter] = current_prime;  
  19.     while ( current_prime < VALS_IN_SIEVE_TABLE )  
  20.     {  
  21.         for ( c = current_prime; c <= VALS_IN_SIEVE_TABLE; c += current_prime )  
  22.         {  
  23.             sieve_table[c] = COMPOSITE;  
  24.         }  
  25.         for ( d=current_prime+1; sieve_table[d] == COMPOSITE; d++ );  
  26.             prime_table[++prime_counter] = d;  
  27.         current_prime = d;  
  28.     }  
  29. }  
  30.   
  31. void main(void)  
  32. {  
  33.     char *query_string;  
  34.     long int n;  
  35.     initialize_prime_table();  
  36.       
  37.     while( FCGI_Accept() >= 0 )  
  38.     {  
  39.         printf( "Content-type: text/html\r\n\r\n" );  
  40.         printf( "<title>Prime FastCGI</title>\n"  
  41.             "<h1>Prime FastCGI</h1>\n" );  
  42.         query_string = getenv( "QUERY_STRING" );  
  43.         if( query_string == NULL )  
  44.         {  
  45.             printf("Usage: Specify a positive number in the query string.\n");  
  46.         }  
  47.         else  
  48.         {  
  49.             query_string = strchr(query_string, '=') + 1;  
  50.             n = strtol(query_string);  
  51.             if ( n < 1 )  
  52.             {  
  53.                 printf( "The query string '%s' is not a positive number.\n", query_string );  
  54.             }  
  55.             else if ( n > MAX_NUMBER_OF_PRIME_NUMBERS )  
  56.             {  
  57.                 printf( "The number %d is too large for this program.\n", n );  
  58.             }  
  59.             else  
  60.             {  
  61.                 printf( "The %ldth prime number is %ld.\n", n, prime_table[n] );  
  62.             }  
  63.         }  
  64.     }  
  65. }  

  这个应用程序在初始化时有一个显而意见的开销,但是后来的访问是快速的。

0 0
原创粉丝点击