使用C++编写CGI程序

一.基本原理

CGI全称Common Gateway Interface(通用网关接口),是一种编程接口,不论什么语言,只要按照该接口的标准编写出来的程序,即可叫做CGI程序,CGI 程序的输入/输出是使用编程语言的标准输入/标准输出,所以用C/C++来写 CGI 程序就好像写普通程序一样,通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。

组成CGI通信系统的是两部分:一部分是html页面,就是在用户端浏览器上显示的页面。另一部分则是运行在服务器上的CGI程序。

它们之间的通讯方式如下图:

 

       服务器和客户端之间的通信,是客户端的浏览器和服务器端的http服务器之间的HTTP通信,我们只需要知道浏览器请求执行服务器上哪个CGI程序就可以了,其他不必深究细节,因为这些过程不需要程序员去操作。

       服务器和CGI程序之间的通讯才是我们关注的。一般情况下,服务器和CGI程序之间是通过标准输入输出来进行数据传递的,而这个过程需要环境变量的协作方可实现。

   1.    服务器将URL指向一个应用程序

   2.    服务器为应用程序执行做准备

   3.    应用程序执行,读取标准输入和有关环境变量

   4.    应用程序进行标准输出

对于Windows系统而言,还可以通过profile文件进行数据传输(如ini文件),但在这里不做研究。环境变量在CGI中有着重要的地位!每个CGI程序只能处理一个用户请求,所以在激活一个CGI程序进程时也创建了属于该进程的环境变量。

 

二.环境变量

       对于CGI程序来说,它继承了系统的环境变量。CGI环境变量在CGI程序启动时初始化,在结束时销毁。

       当一个CGI程序不是被HTTP服务器调用时,它的环境变量几乎是系统环境变量的复制。

   当这个CGI程序被HTTP服务器调用时,它的环境变量就会多了以下关于HTTP服务器,客户端,CGI传输过程等项目。

 

与请求相关的环境变量

REQUEST_METHOD

服务器与CGI程序之间的信息传输方式

QUERY_STRING

采用GET时所传输的信息

CONTENT_LENGTH

STDIO中的有效信息长度

CONTENT_TYPE

指示所传来的信息的MIME类型

CONTENT_FILE

使用Windows HTTPd/WinCGI标准时,用来传送数据的文件名

PATH_INFO

路径信息

PATH_TRANSLATED

CGI程序的完整路径名

SCRIPT_NAME

所调用的CGI程序的名字

与服务器相关的环境变量

GATEWAY_INTERFACE

服务器所实现的CGI版本

SERVER_NAME

服务器的IP或名字

SERVER_PORT

主机的端口号

SERVER_SOFTWARE

调用CGI程序的HTTP服务器的名称和版本号

与客户端相关的环境变量

REMOTE_ADDR

客户机的主机名

REMOTE_HOST

客户机的IP地址

ACCEPT

例出能被次请求接受的应答方式

ACCEPT_ENCODING

列出客户机支持的编码方式

ACCEPT_LANGUAGE

表明客户机可接受语言的ISO代码

AUTORIZATION

表明被证实了的用户

FORM

列出客户机的EMAIL地址

IF_MODIFIED_SINGCE

当用get方式请求并且只有当文档比指定日期更早时才返回数据

PRAGMA

设定将来要用到的服务器代理

REFFERER

指出连接到当前文档的文档的URL

USER_AGENT

客户端浏览器的信息

    CONTENT_TYPE:如application/x-www-form-urlencoded,表示数据来自HTML表单,并且经过了URL编码。

  ACCEPT:客户机所支持的MIME类型清单,内容如:”image/gif,image/jpeg”

    REQUEST_METHOD:它的值一般包括两种:POST和GET,但我们写CGI程序时,最后还要考虑其他的情况。

1.POST方法

如果采用POST方法,那么客户端来的用户数据将存放在CGI进程的标准输入中,同时将用户数据的长度赋予环境变量中的CONTENT_LENGTH。客户端用POST方式发送数据有一个相应的MIME类型(通用Internet邮件扩充服务),

目前,MIME类型一般是:application/x-wwww-form-urlencoded,该类型表示数据来自HTML表单。该类型记录在环境变量CONTENT_TYPE中,CGI程序应该检查该变量的值。

2.GET方法

在该方法下,CGI程序无法直接从服务器的标准输入中获取数据,因为服务器把它从标准输入接收到得数据编码到环境变量QUERY_STRING(或PATH_INFO)

GET与POST的区别:采用GET方法提交HTML表单数据的时候,客户机将把这些数据附加到由ACTION标记命名的URL的末尾,用一个包括把经过URL编码后的信息与CGI程序的名字分开:例如: http://www.mycorp.com/hello.html?name=hgq$id=1,QUERY_STRING的值为name=hgq&id=1, 有些程序员不愿意采用GET方法,因为在他们看来,把动态信息附加在URL的末尾有违URL的出发点:URL作为一种标准用语,一般是用作网络资源的唯一定位标示。

环境变量是一个保存用户信息的内存区。当客户端的用户通过浏览器发出CGI请求时,服务器就寻找本地的相应CGI程序并执行它。在执行CGI程序的同时,服务器把该用户的信息保存到环境变量里。接下来,CGI程序的执行流程是这样的:查询与该CGI程序进程相应的环境变量:第一步是request_method,如果是POST,就从环境变量的len,然后到该进程相应的标准输入取出len长的数据。如果是GET,则用户数据就在环境变量的QUERY_STRING里。

3.POST与GET的区别

以GET方式接收的数据是有长度限制,而用POST方式接收的数据是没有长度限制的。并且,以GET方式发送数据,可以通过URL的形式来发送,但POST方式发送的数据必须要通过Form才到发送。

 

三.CGI程序案例

1. CGI服务端程序

/*
* req_method.c
* Path: uc_cgi/WEB_INF/cgi/test02/req_method.c * Created on: Oct 31, 2016 * Author: zhangming
*/ #include <stdio.h> #include <stdlib.h> #define MAXLEN 80 int main(int argc, char **argv) { char* pRequestMethod; printf("Content-Type:text/html\n\n"); setvbuf(stdin,NULL,_IONBF,0); pRequestMethod = getenv("REQUEST_METHOD"); if(strcmp(pRequestMethod,"POST") == 0){ printf("<TITLE>This is Post operation</TITLE>\n"); char poststr[80]; char *lenstr = getenv("CONTENT_LENGTH"); if(lenstr == NULL){ printf("<P>Post form error"); }else{ long len = atoi(lenstr); fgets(poststr,len+1,stdin); printf("%s",poststr); } } if(strcmp(pRequestMethod,"GET") == 0){ printf("<TITLE>This is Get operation</TITLE>\n"); char *qa; printf("<TITLE>The reault of Get is:\n</TITLE>\n"); qa = getenv("QUERY_STRING"); printf("%s",qa); } }

2. 客户端html页面

<!-- Path: uc_cgi/req_method.html -->
<html>

<body>

<h2>request method test</h2>

 

<FORM ACTION="./cgi-bin/test02/req_method" METHOD="get">

<INPUT TYPE="text" NAME="Text" VALUE="">

<INPUT TYPE="submit" VALUE="Get"></INPUT>

</FORM>

<BR> 

 

<FORM ACTION="./cgi-bin/test02/req_method" METHOD="post">

<INPUT TYPE="text" NAME="Text" VALUE="">

<INPUT TYPE="submit" VALUE="Post"></INPUT>

</FORM>

<BR>

 

</body>

</html>

3. 运行结果截图

(1).原始输入界面

(2).GET请求返回的界面

(3).POST请求返回的界面

posted @ 2016-11-01 16:10  水火379  阅读(1105)  评论(0)    收藏  举报