原文:http://blog.csdn.net/duola_rain/article/details/15812585

CGI接口原理及实现(2012-12-7 Over)


1.CGI定义:

CGI(CommonGateway Interface)是HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上

2.CGI功能:

绝大多数的CGI程序被用来解释处理来自表单的输入信息,并在服务器产生相应的处理,或将相应的信息反馈给浏览器。CGI程序使网页具有交互功能。

3.CGI运行环境:

CGI程序在UNIX操作系统上CERN或NCSA格式的服务器上运行。 在其它操作系统(如:windows NT及windows95等)的服务器上 也广泛地使用CGI程序,同时它也适用于各种类型机器。

4.CGI处理步骤:

⑴通过Internet把用户请求送到服务器。

⑵服务器接收用户请求并交给CGI程序处理。

⑶CGI程序把处理结果传送给服务器。

⑷服务器把结果送回到用户。

5.CGI服务器配置:

在许多服务器cgi-bin是仅能够放置CGI脚本的目录。

在Windows平台上将C或C++写好的程序的Debug或Release版本的.exe程序拷贝到cgi-bin的目录下(如上图所示),将.exe改为.cgi也可同样运行,如下2个图。

       cgi-bin目录是存放CGI脚本的地方。这些脚本使WWW服务器和浏览器能运行外部程序,而无需启动另一个程序。它是运行在Web服务器上的一个程序,并由来自于浏览者的输入触发。

CGI程序不是放在服务器上就能顺利运行,如果要想使其在服务器上顺利的运行并准确的处理用户的请求,则须对所使用的服务器进行必要的设置。

       配置:根据所使用的服务器类型以及它的设置把CGI程序放在某一特定的目录中或使其带有特定的扩展名。

Apache网络服务器配置在/var/www/cgi-bin里(如下图所示笔者电脑的目录位置)。C++编译的可执行文件可以转换成扩展名为.cgi的文件。

更改初始配置的的方法:

<Directory"/var/www/cgi-bin">

AllowOverride None

Options ExecCGI

Order allow,deny

Allow from all

</Directory>

<Directory"/var/www/cgi-bin">

Options All

</Directory>

6.CGI接口标准包括标准输入、环境变量、标准输出三部分。

介绍

1.标准输入

CGI程序像其他可执行程序一样,可通过标准输入(stdin)从Web服务器得到输入信息,如Form中的数据,这就是所谓的向CGI程序传递数据的POST方法。这意味着在操作系统命令行状态可执行CGI程序,对CGI程序进行调试。POST方法是常用的方法。

2.环境变量

操作系统提供了许多环境变量,它们定义了程序的执行环境,应用程序可以存取它们。Web服务器和CGI接口又另外设置了自己的一些环境变量,用来向CGI程序传递一些重要的参数。CGI的GET方法还通过环境变量QUERY-STRING向CGI程序传递Form中的数据。

3.标准输出

CGI程序通过标准输出(stdout)将输出信息传送给Web服务器。传送给Web服务器的信息可以用各种格式,通常是以纯文本或者HTML文本的形式,这样我们就可以在命令行状态调试CGI程序,并且得到它们的输出。

7.环境变量

  环境变量是文本串(名字/值对),可以被OSShell或其他程序设置 ,也可以被其他程序访问。它们是Web服务器传递数据给CGI程序的简单手段,之所以称为环境变量是因为它们是全局变量,任何程序都可以存取它们。

下面是CGI程序设计中常常要用到的一些环境变量。

环境变量         
意义

SERVER_NAME

CGI脚本运行时的主机名和IP地址.

SERVER_SOFTWARE

你的服务器的类型如: CERN/3.0 或 NCSA/1.3.

GATEWAY_INTERFACE

运行的CGI版本. 对于UNIX服务器, 这是CGI/1.1.

SERVER_PROTOCOL

服务器运行的HTTP协议. 这里当是HTTP/1.0.

SERVER_PORT

服务器运行的TCP口,通常Web服务器是80.

REQUEST_METHOD

POST 或 GET, 取决于你的表单是怎样递交的.

HTTP_ACCEPT

浏览器能直接接收的Content-types, 可以有HTTP Accept header定义.

HTTP_USER_AGENT

递交表单的浏览器的名称、版本 和其他平台性的附加信息。

HTTP_REFERER

递交表单的文本的 URL,不是所有的浏览器都发出这个信息,不要依赖它

PATH_INFO

附加的路径信息, 由浏览器通过GET方法发出.

PATH_TRANSLATED

在PATH_INFO中系统规定的路径信息.

SCRIPT_NAME

指向这个CGI脚本的路径, 是在URL中显示的(如, /cgi-bin/thescript).

QUERY_STRING

脚本参数或者表单输入项(如果是用GET递交). QUERY_STRING包含URL中问号后面的参数.

REMOTE_HOST

递交脚本的主机名,这个值不能被设置.

REMOTE_ADDR

递交脚本的主机IP地址.

REMOTE_USER

递交脚本的用户名. 如果服务器的authentication被激活,这个值可以设置。

REMOTE_IDENT

如果Web服务器是在ident (一种确认用户连接你的协议)运行, 递交表单的系统也在运行ident, 这个变量就含有ident返回值.

CONTENT_TYPE

如果表单是用POST递交, 这个值将是 application/x-www-form-urlencoded. 在上载文件的表单中, content-type 是个 multipart/form-data.

CONTENT_LENGTH

对于用POST递交的表单,标准输入口的字节数.

REQUEST-METHOD:指的是当Web服务器传递数据给CGI程序时所采用的方法,分为GET和POST两种方法。

GET和POST方法的区别】:GET方法仅通过环境变量(如QUERY-STRING)传递数据给CGI程序,而POST方法通过环境变量和标准输入传递数据给CGI程序,因此POST方法可较方便地传递较多的数据给CGI程序。

问题

GET方法

通过在URL中嵌入的形式传递参数。对CGI程序而言,在GET method中传递的参数要通过化境变量“QUERY-STRING”来接收。

1)  参数的内容作为URL信息,用户可以看到;

2)  有大小的限制。

POST方法

CGI程序从标准输入接收参数。与GET方法不同的是,参数的内容从URL信息中不能获得,对于大小也没有限制。

与GET方法问题1),2)完全相反。

CONTENT-LENGTH:传递给CGI程序的数据字符数(字节数)。

在C语言程序中,要访向环境变量,可使用getenv()库函数。例如:
       if (getenv (″CONTENT-LENGTH″))n=atoi(getenv(″CONTENT-LENGTH″));
  请注意程序中最好调用两次getenv():第一次检查是否存在该环境变量,第二次再使用该环境变量。这是因为函数getenv()在给定的环境变量名不存在时,返回一个NULL(空)指针,如果你不首先检查而直接引用它,当该环境变量不存在时会引起CGI程序崩溃。

8. CGI的工作原理

CGI是一个WEB服务器提供信息服务的标准接口,通过这样一个接口,WEB服务器能够执行程序,并将程序输出的信息返回给浏览器。因为在WEB网上的数据都是静态的,通过CGI程序能够动态的处理浏览者的请求,如保存用户输入的信息,根据用户信息返回相关的资料等等。当客户端发送一个CGI请求给WEB服务器后,WEB服务器将根据CGI程序的类型决定数据向CGI程序的传送方式,一般来讲是通过标准输入/输出流和环境变量来与CGI程序间传递数据。

CGI输入输出原理

CGI的输入/输出方法:CGI程序通过标准输入(STDIN)和标准输出(STDOUT)来进行输入输出,STDIN和STDOUT是两个预先定义好的文件指针。你可以利用文件读写函数来对其进行操纵。

此外CGI程序还通过环境变量来得到输入,只不过环境变量中提供的是一些常用的信息,并且通常不包括用户在WEB页面中输入的信息(除使用下面讲的GET方法时,通过检查环境变量QUERY_STRING来得到输入数据),而STDIN通常用来传递用户输入的信息。

在输入时所使用的POST/GET方法:在WEB页面向CGI发送数据时通常采用两种方法:GET/POST,GET方法将数据附加在URL后发送,如:/cgi/a_cgi_test.exe?your_data,CGI程序通过检查环境变量QUERY_STRING来得到输入数据。

        示例一、下图即是GET方法!


上图的对应程序为:

//2012-12-5 GET c程序示例..

  1. void main(void)
  2. {// 本程序将用户输入的数据打印出来
  3. fprintf(stdout,"content-type:text/plain\n\n");
  4. // 输出一个CGI标题,这行代码的意义后面会讲解
  5. char *pszMethod;
  6. pszMethod =getenv("REQUEST_METHOD");
  7. if(strcmp(pszMethod,"GET") == 0)
  8. {     //GET method
  9. //读取环境变量来获取数据
  10. printf("This is GETMETHOD!\n");
  11. printf("SERVER_NAME:%s\n",getenv("SERVER_NAME"));
  12. printf("REMOTE_ADDR:%s\n",getenv("REMOTE_ADDR"));
  13. fprintf(stdout,"input data is:%s\n",getenv("QUERY_STRING"));
  14. }
  15. else
  16. {  // POST method
  17. //读取STDIN来获取数据
  18. intiLength=atoi(getenv("CONTENT_LENGTH"));
  19. printf("This is POSTMETHOD!\n");
  20. fprintf(stdout,"input data is:\n");
  21. for(int i=0;i<iLength;i++)
  22. {
  23. char cGet=fgetc(stdin);
  24. fputc(cGet,stdout);
  25. }
  26. }
  27. }

         示例二、下图即是POST程序示例:




  1. void unencode(char *src, char *last, char *dest)
  2. {
  3. // str = hello+there%21 此处跳过data=...
  4. // last = ; 已到末尾.
  5. // dest= ; 空串.
  6. //解码原则
  7. //原则1: '+'变' ';
  8. //原则2: '%xx'变成对应的16进制ASCII码值;
  9. for(; src != last; src++, dest++)
  10. {
  11. if(*src == '+')
  12. {
  13. *dest = ' ';
  14. }
  15. else if(*src == '%')
  16. {
  17. int code;
  18. if(sscanf(src+1, "%2x", &code) != 1)
  19. {
  20. code = '?';
  21. }
  22. *dest = code;
  23. src +=2;
  24. }
  25. else
  26. {
  27. *dest = *src;
  28. }
  29. }
  30. *dest = '\n';
  31. *++dest = '\0';
  32. }
  33. intmain(void)
  34. {
  35. char *lenstr;
  36. char input[MAXINPUT], data[MAXINPUT];
  37. long len;
  38. printf("%s%c%c\n","Content-Type:text/html;charset=iso-8859-1",13,10);
  39. printf("<TITLE>Response</TITLE>\n");
  40. lenstr =getenv("CONTENT_LENGTH");
  41. printf("CONTENT_LENGTH =%s\n",lenstr);
  42. if(lenstr == NULL ||sscanf(lenstr,"%ld",&len)!=1 || len > MAXLEN)
  43. {
  44. printf("<P>Error ininvocation - wrong FORM probably.");
  45. }
  46. else
  47. {
  48. FILE *f;
  49. fgets(input, len+1, stdin);           //add by ycy从输入流中获取字符串.
  50. unencode(input+EXTRA, input+len,data);
  51. f = fopen(DATAFILE,"a");
  52. if(f == NULL)
  53. {
  54. printf("<P>Sorry,cannot store your data.");
  55. }
  56. else
  57. {
  58. fputs(data, f); //add byycy 将数据存储在对对应的文件中.
  59. }
  60. fclose(f);
  61. printf("<P>Thank you!Your contribution has been stored.");
  62. }
  63. return 0;
  64. }

    请求过程即是:

(1)      send发送按钮--->(2)调用post.cgi--->(3)将数据存储在data\data.txt里面。

       示例三、下图即是GET/POST程序示例。

综合实例:在上面两个程序上的扩展(应用Get方法及QUERY_STRING),

如上两图所示,在表单(cgi接口的表单只是在html语言的基础上用C或C++实现的扩展操作而已)的基础上,提交按钮对应的另一个CGI接口(6.exe或6.cgi),这样通过Get方法及QUERY_STRING参量就可以完成输出操作。

而POST方法则会将数据送入CGI程序的STDIN输入流。在表单(FORM)中的各个变量都会成为name=value的形式向WEB服务器发送,多个数据间用&分隔,如:name=value&name2=value2。其中名字(name,name2)是Form中定义的INPUT、SELECT或TEXTAREA等标置(Tag)名字,值是用户输入或选择的标置值。

如上面说讲,在CGI程序输出时必须先输出一个CGI标题,标题共有以下三类:

·      Location: 标题,指明输出另一个文档的URL,例如 fprintf(stdout,"Location:http://www.vchelp.net/\n\n");

·      Content-Type: 标题,指明发送的数据的MIME类型,例如 fprintf(stdout,"Content-Type:text/html\n\n");

·      Status: 标题,指明HTTP状态码,例如 fprintf(stdout,"Status:200\n\n");

注意每种标题后都必须跟一个换行和一个空行。

MIME类型以类型/子类型的形式来表示,下面是一些常用的类型/子类型的组合:

·      Text/plain 普通文本类型

·      Text/html HTML格式的文本类型

·      Audio/basic 八位声音文件格式,后缀为.au

·      Video/mpeg MPEG文件格式

·      Video/quicktime QuickTime文件格式

·      Image/gif GIF图形文件

·      Image/jpeg JPEG图形文件

·      Image/x-xbitmap X bitmap图形文件,后缀为.xbm

有了上面的知识我们就可以写出一些CGI程序,首先需要对输入数据进行分析,方法为:每当找到字符=,标志着一个Form变量名字的结束;每当找到字符& ,标志着一个Form变量值的结束。请注意输入数据的最后一个变量的值不以&结束。这样我们可以将输入数据分解为一组一组的值。

但随后会发现CGI的输入并不规则,例如有时会出现类似下面格式的输入字符号串:filename=hello&cmd=world+I%27,这是因为浏览器对一些上传的特殊字符进行了编码,所以在将数据分解开后需要进行解码,

     解码规则为

1)+: 将+转换成空格符;

2) %xx: 用其十六进制ASCII码值表示的特殊字符(%作为为转意符)。根据值xx将其转换成相应的ASCII字符。对Form变量名和变量值都要进行这种转换。

CGI接口原理及实现(转载)的更多相关文章

  1. CGI技术原理

    一.CGI技术 1.1 CGI的提出 CGI是外部扩展应用程序与WWW服务器交互的一个标准接口.按照CGI标准编写的外部扩展应用程序可以处理客户端(一般是WWW浏览器)输入的协同工作数据,完成客户端与 ...

  2. 【转】Android LCD(二):LCD常用接口原理篇

    关键词:android LCD TFT TTL(RGB)  LVDS  EDP MIPI  TTL-LVDS  TTL-EDP 平台信息:内核:linux2.6/linux3.0系统:android/ ...

  3. (转)LCD:LCD常用接口原理篇

    关键词:android LCD TFT TTL(RGB)  LVDS  EDP MIPI  TTL-LVDS  TTL-EDP平台信息:内核:linux2.6/linux3.0系统:android/a ...

  4. LCD常用接口原理【转】

    转自:http://blog.csdn.net/wocao1226/article/details/23870149 LCD常用接口原理 点击打开链接 点击打开链接 点击打开链接 点击打开链接 点击打 ...

  5. Android LCD(二):LCD常用接口原理篇(转)

    源: Android LCD(二):LCD常用接口原理篇

  6. 嵌入式物联网之SPI接口原理与配置

    本实验采用W25Q64芯片 W25Q64是华邦公司推出的大容量SPI FLASH产品,其容量为64Mb.该25Q系列的器件在灵活性和性能方面远远超过普通的串行闪存器件.W25Q64将8M字节的容量分为 ...

  7. Fast CGI 工作原理

    http://www.cppblog.com/woaidongmao/archive/2011/06/21/149092.html 一.FastCGI是什么? FastCGI是语言无关的.可伸缩架构的 ...

  8. NET/ASP.NET Routing路由(深入解析路由系统架构原理)(转载)

    NET/ASP.NET Routing路由(深入解析路由系统架构原理) 阅读目录: 1.开篇介绍 2.ASP.NET Routing 路由对象模型的位置 3.ASP.NET Routing 路由对象模 ...

  9. NEO VM原理及其实现(转载)

    NEO Vm原理及其实现 简介及与evm主要区别 neo vm和evm类似.底层都实现了一套opcode以及对应的执行器,opcode设计差距蛮大的,总体上来说evm的更加简洁,neo vm的功能更加 ...

随机推荐

  1. JAVA源码分析-HashMap源码分析(一)

    一直以来,HashMap就是Java面试过程中的常客,不管是刚毕业的,还是工作了好多年的同学,在Java面试过程中,经常会被问到HashMap相关的一些问题,而且每次面试都被问到一些自己平时没有注意的 ...

  2. ubuntu14.04 wifi驱动

    ubuntu崩溃后再安装后,发现没有了wifi按钮 因为必须要用wifi不然太不方便了,于是在网上找了一下,安装了一下驱动就解决了 首先确定无线网卡类型: $ lspci -vnn -d 14e4: ...

  3. UnsupportedClassVersionError: Bad version number in .class file

    java.lang.UnsupportedClassVersionError: Bad version number in .class file造成这种过错是ni的支撑Tomcat运行的JDK版本与 ...

  4. UE4 编译后 不能正常使用Open Level 打开关卡解决方案:Open Level Blueprint Node not workin

    配置DefaultEditor.ini 文件 [AllMaps] +Map=/关卡文件路径   参考文献: https://answers.unrealengine.com/questions/141 ...

  5. python数字图像处理(4):图像数据类型及颜色空间转换

    一.图像数据类型及转换 在skimage中,一张图片就是一个简单的numpy数组,数组的数据类型有很多种,相互之间也可以转换.这些数据类型及取值范围如下表所示: Data type Range uin ...

  6. 【BZOJ】【1049】【HAOI2006】数字序列

    DP 第一问比较水……a[i]-=i 以后就变成最长不下降子序列问题了,第二问这个结论好神奇,考试的时候怎么破?大胆猜想,不用证明?TAT 题解:http://pan.baidu.com/share/ ...

  7. IO-04. 混合类型数据格式化输入

    /** *A4-IO-04. 混合类型数据格式化输入 *C语言实现 *测试已通过 */ #include "stdio.h" int main() { float m1,m2; i ...

  8. JAVA课设--五子棋--团队博客

    1 团队名称.团队成员介绍 徐璐琳 网络1511班 201521123010 祁泽文 网络1511班 201521123011 张晨晨 网络1511班 201521123009 2 项目git地址 团 ...

  9. 怎样实现给DEDE的栏目增加栏目图片(1)

    http://www.genban.org/news/dedecms-7577.html 前两天用DEDE做二次开发的时候,遇到一个问题,领导让给每个栏目增加一个栏目图片的功能,网上找了些东西,结合自 ...

  10. FPM三:简单的SEARCH(OIF)

    这里是使用FPM Workbench自动生成的,没有去SE80创建WDA程序. 1.使用事务代码:FPM_WB.打开工作台. 2.点击Wizard for Creating Empty FPM App ...