One. Basic Principles
CGI: Common Gateway Interface (Common Gateway Interface) is a Web server host to provide a standard interface for information services. Through the CGI interface, the Web server can obtain the information submitted by the client , Transfer it to the CGI program on the server side for processing, and finally return the result to the client.
The CGI communication system is composed of two parts: one part is html page is the page displayed on the client browser. The other part is the Cgi program running on the server.
The communication between them is shown in the figure below:
Server p> |
Client |
CGIProgram |
HTTP communication |
Standard input Output (environment variable) |
The communication between the server and the client is between the browser of the client and the serverhttpthe server HTTPcommunication, we only need to know which browser request is executed on the serverCGIThe program is fine, and you don’t need to go into the details because these processes do not require programmers to operate.
Server and< /span>CGIThe communication between programs is what we care about. Under normal circumstances, the server and the CGI program pass standard input and output for data transmission, and This process requires the cooperation of environment variables to be realized.
< p>1. The server will pointURL to an application Program
2. The server prepares for application execution< /span>
3. < span style="font-size:14px">application execution, read standard input and related environment variables p>
4. The application performs standard output
ForWindowssystem, you can also use profilefile for data transfer (e.g.inifile), but here
here Don’t do research.
Environment variables are inCGI has an important position! Each CGI program can only process one user request, so it’s aggressive
Live oneCGI The environment variables belonging to the process are also created during the process of the program.
< h2>Two. Environment variables
For CGI program, it inherits the environment variables of the system. CGIEnvironment variables are inCGIInitialize when the program starts, and destroy it when it ends.
When aCGIprogram is not being usedHTTP When the server is called, its environment variables are almost copies of system environment variables.
When thisCGIThe program is usedHTTPserver When it is called, its environment variables will be more. The following AboutHTTPserver, client,CGITransmission process and other items.
< p>
< td valign="top">
ACCEPT_ENCODING
< tr>
Environmental variables related to the request < /td> |
REQUEST_METHOD< /strong> |
The information transmission method between the server andCGIprogram< /p> |
QUERY_STRING |
AdoptGETthe information transmitted at the time |
|
CONTENT_LENGTH |
STDIO Effective message length in |
|
CONTENT_TYPE |
< p align="center">indicating the information passed MIMEType | |
CONTENT_FILE |
When usingWindows HTTPd/WinCGIstandard, the file name used to transmit data< /span> |
|
PATH_INFO |
Path information |
|
PATH_TRANSLATED |
CGIThe full path name of the program |
|
SCRIPT_NAME |
Adjusted UsedCGIThe name of the program |
|
Environmental variables related to the server |
GATEWAY_INTERFACE |
implemented by the server< /span>CGIversion |
SERVER_NAME |
serverIPor name |
|
SERVER_PORT |
the port number of the host |
|
SERVER_SOFTWARE |
callCGI programHTTPserver name and version number |
|
Environmental variables related to the client |
REMOTE_ADDR |
Host name of the client |
REMOTE_HOST |
Client’sIPAddress |
|
ACCEPT |
Examples of response methods that can be accepted by this request |
|
List the encoding methods supported by the client |
||
< p align="center">ACCEPT_LANGUAGE |
indicating that the client can accept languagesISOcode |
|
AUTORIZATION |
indicating users who have been verified |
|
FORM |
list the client’sEMAILAddress |
|
IF_MODIFIED_SINGCE |
when usedgetrequest and return data only when the document is older than the specified date |
|
PRAGMA |
Set the server proxy to be used in the future |
|
REFFERER |
points out the document linking to the current documentURL |
|
USER_AGENT |
Client browser information |
CONTENT_TYPE:For exampleapplication/x-www-form-urlencoded, it means the data comes fromHTMLform and passedURLCode.
ACCEPT:MIMElist of types supported by the client, such as:“image/gif,image/jpeg”
REQUEST_METHOD: Its value generally includes two types:POSTandGET, but we writeCGIWhen programming, there are other things to consider at the end.
1. POST method
if Using the POST method, then the user data from the client will be stored inCGIIn the standard input of the process, at the same time assign the length of the user data to CONTENT_LENGTH. The client uses POST to send data with a correspondingMIMEType (genericInternet Mail extension service:Multi-purpose Internet Mail Extensions). At present,MIMEThe general type is:application /x-wwww-form-urlencoded, this type indicates that the data comes fromHTMLForm. This type is recorded in the environment variableCONTENT_TYPE,CGIThe program should check the value of this variable.
2. GETMethod
Under this method,CGIThe program cannot be directly Get the data from the standard input of the server, because the server takes it from the standard
Encode the received data into an environment variableQUERY_STRING(orPATH_INFO).
GETDifferences fromPOST: use When GETmethod submitHTMLform data , The client will append these data
data to the span>ACTIONTag-namedURL< At the end of span style="color:black">, use an include to include the encoded information after URL Separate fromCGIthe name of the program:http ://www.mycorp.com/hello.html? name=hgq$id=1, The value of QUERY_STRINGname=hgq&id=1
< p>Some programmers are reluctant to useGET< span style="color:black"> method, because in their opinion, append dynamic information to URL At the end has
violationURL:URLAs a standard term, it is generally used as the only location indicator for network resources.
< p>Environment variable is a memory area that saves user information. When a client user sends a request via a browserCGI, the server looks for the local corresponding CGI program and execute it. While executing the CGI program, the server saves the user’s information in the environment variable. Next,CGIThe execution flow of the program is like this: query and thisCGIThe corresponding environment variables of the program process: The first step isrequest_method span>, if it’sPOST, from the environment variable len, and then go to the corresponding standard input of the process to take outlenLong data. If it isGET, the user data is in the environment variableQUERY_STRINGin.
3. POSTandGET< span style="color:black">the difference
in The data received by GET has a length limitation, while the data received by POST There is no length limit. And, to send data in the form of GET, it can be sent in the form of URL Send, but the data sent by POST must be sent through Form send.
Three. CGI program implementation steps
1. Get data from the server
CLanguage implementation Code:
#include #include < p>#include
int get_inputs() { int length; < p>char *method;
method = getenv(“REQUEST_METHOD”); // Give the returned result to a pointer if(method == NULL) return 1; //Cannot find environment variableREQUEST_METHOD if(!strcmp(method, ”POST”))// POSTMethod { length = atoi(getenv(“CONTENT_LENGTH”)); //< span style="color:black">The result is a character, which needs to be converted if(length != 0) { inputstring = malloc(sizeof(char)*length + 1) //must apply for cache, becausestdin is not cached. fread(inputstring, sizeof(char), length, stdin); //Read certain data from standard input < span style="font-size:14px">} } else if(!strcmp(method, “GET”)) { Inputstring = getenv(“QUERY_STRING”); < span style="color:black"> length = strlen(inputstring); } if(length == 0) return 0; }< /p> |
PerlImplementation code:
$method = $ENV{‘REQUEST_METHOD’}; if($method eq’POST’) { Read(STDIN, $input, $ENV{‘CONTENT_LENGTH’}); } if($method eq’GET’ || $method eq’HEAD’) < span style="color:black">{ $input = $ENV{‘QUERY_STRING’}; } if($input eq “”) {< /p> &print_form; exit; } |
PYTHONCode implementation
< /p>
#!/usr/local/bin/python import cgi def main(): form = cgi.FieldStorage()
< p>PythonThe code implementation is simpler,cgi.FieldStorage()returns a dictionary, each one of the dictionarykey is the variable name,keycorresponding value It is the value of the variable name, and there is no need for the user to decode the data! |
When obtaining environment variables, if you first judge “REQUEST_METHOD “If it exists, the program will be more robust, otherwise it may cause the program to crash in some cases. Because ifCGIthe program is not called by the server, then there is no difference in the environment variable set CGIRelated environment variables (e.g.REQUEST_METHOD ,REMOTE_ADDRetc.), which means “< /span>getenv(“REQUEST_METHOD”)“will return NULL!
2. URLencoding
whether it isPOST or< span style="color:black">GETThe data sent by the client browser to the server is not the original user data, but passed< span style="color:black">URLencoded. At this time, CGIEnvironment variablesContent_type will be set, such asContent_type = application/x-www-form-urlencode means that what the server received is a URLencoded containing< /span>HTML表单变量数据。
编码的基本规则是:
变量之间用“&”分开;
变量与其对应值用“=”连接;
空格用“+”代替;
保留的控制字符则用“%”连接对应的16禁止ASCII码代替;
某些具有特殊意义的字符也用“%”接对应的16进制ASCII码代替;
空格是非法字符;
任意不可打印的ASCII控制字符均为非法字符。
例如,假设3个HTML表单变量filename、e-mail和comments,它们的值对应分别为hello、mike@hotmail.com和I’ll be there for you,则经过URL编码后应为:
filename=hello&e-mail=hello@hotmail.com&comments=I%27ll+be+there+for+you
|
所以,CGI程序从标准输入或环境变量中获取客户端数据后,还需要进行解码。解码的过程就是URL编码的逆变:根据“&”和“=”分离HTML表单变量,以及特殊字符的替换。
在解码方面,PYTHON代码实现是最理想的,cgi.FieldStorage()函数在获取数据的同时就已自动进行代码转换了,无需程序员再进行额外的代码编写。 Perl其次,因为在一个现成的Perl库:cgi-lib.pl中提供了ReadParse函数,用它来进行URL解码很简单:
require ‘cgi-lib.pl’; &ReadParse(*input); |
3. CGI数据输出
CGI程序如何将信息处理结果返回给客户端?这实际上是CGI格式化输出。
在CGI程序中的标准输出stdout是经过重定义了的,它并没有在服务器上产生任何的输出内容,而是被重定向到客户浏览器,这与它是由C,还是Perl或Python实现无关。
所以,我们可以用打印来实现客户端新的HTML页面的生成。 比如,C的printf是向该进程的标准输出发送数据,Perl和Python用print向该进程的标准输出发送数据。
(1) CGI标题
CGI的格式输出内容必须组织成标题/内容的形式。 CGI标准规定了CGI程序可以使用
的三个HTTP标题。标题必须占据第一行输出!而且必须随后带有一个空行。
标题 |
描述 |
Content_type (内容类型) |
设定随后输出数据所用的MIME类型 |
Location (地址) |
设定输出为另外一个文档(URL) |
Status (状态) |
指定HTTP状态码 |
MIME:
向标准输出发送网页内容时要遵守MIME格式规则:
任意输出前面必须有一个用于定义MIME类型的输出内容(Content-type)行,而且随后还必须跟一个空行。如果遗漏了这一条,服务将会返回一个错误信息。 (同样使用于其他标题)
例如Perl和Python:
print “Content-type:text/html\n\n”; //输出HTML格式的数据 print “welcome print “” |
C语言:
printf( “Content-type:text/html\n\n”); printf(“Welcome\n”); |
MIME类型以类型/子类型(type/subtype)的形式表示。
其中type表示一下几种典型文件格式的一种:
Text、Audio、Video、Image、Application、Mutipart、Message
Subtype则用来描述具体所用的数据格式。
Application/msword |
微软的Word文件 |
Application/octet-stream |
一种通用的二进制文件格式 |
Application/zip |
Zip压缩文件 |
Application/pdf |
Pdf文件 |
。 . . . . . . . . . . . . . . . . . . . . . . . . . |
。 . . . . . . . . . . . . . . . . . . . . . . . . |
Location:
使用Location标题,一个CGI可以使当前用户转而访问同一服务器上的另外一个程序,甚至可以访问另外一个URL,但服务器对他们的处理方式不一样。
使用Location的格式为:Location:Filename/URL,例如:
print “Location:/test.html\n\n”; 这与直接链接到test.html的效果是一样的。 |
print “Location:http://www.chinaunix.com/\n\n” 由于该URL并不指向当前服务器,用户浏览器并不会直接链接到指定的URL,而是给用户输出提示信息。 |
HTTP状态码:
表示了请求的结果状态,是CGI程序通过服务器用来通知用户其请求是否成功执行的信息码,本文不做研究。
四. CGI中的信号量和文件锁
因为CGI程序时公用的,而WEB服务器都支持多进程运行,因此可能会发生同时有多个用户访问同一个CGI程序的情况。比如,有2个用户几乎同时访问同一个CGI程序,服务器为他们创建了2个CGI程序进程,设为进程A和进程B。假如进程A首先打开了某个文件,然后由于某种原因被挂起(一般是由于操作系统的进程调度);而就在进程A被挂起的这段时间内,进程B完成了对文件的整个操作流程:打开,写入,关闭;进程A再继续往下执行,但进程A所操作的文件依旧是原来文件的就版本,此时进程A的操作结果将覆盖进程B的操作结果。
为了防止这种情况发生,需要用到文件锁或者信号量。
钥匙文件?
假如有多个不同的HTML可以调用同一个CGI程序,那么CGI程序如何区分它们呢?一个是通过隐含的INPUT标签。不过觉得这个比较麻烦,因为CGI必须经过一系列解码后才能找到这个隐含INPUT的变量和其值。
五.设置HTTP服务器以兼容CGI
用Perl编写的CGI程序后缀为:.pl;Python编写的CGI程序后缀为:.py;而C编写的CGI程序后缀为:.cgi,如果在win下编译出来的是.exe,最好将它重命名为.cgi。这些都是为了HTTP服务能够识别并调用它们。
当使用appche httpd服务器时,请编辑它的配置文件httpd.conf如下:
修改AddHandler cgi-script一句为AddHandler cgi-script .cgi .py .pl
六.关于CGI的C语言库——cgihtml
Cgihtml是一个应用非常广泛的C语言编写的CGI库。它提供的功能函数如下:
Read_cgi_input():获取并解析HTML表单输入,返回一个指向某结构体的指针
Cgi_val():获取每个表单变量的值
Html_header():输出HTML标题栏
Html_begin():输出HTML文档的开始部分
H1():输出一行字符,字体为H1
Html_end():输出HTML文档的结尾部分。
#include “cgi-lib.h”
#include “html-lib.h”
#include “string-lib.h”
六.后话
有的人认为可以用JavaScript来代替CGI程序,这其实是一个概念上的错误。 JavaScript只能够在客户浏览器中运行,而CGI却是工作在服务器上的。他们所做的工作有一些交集,比如表单数据验证一类的,但是JavaScript是绝对无法取代CGI的。但可以这样说,如果一项工作即能够用JavaScript来做,又可以用CGI来做,那么绝对要使用JavaScript,在执行的速度上,JavaScript比CGI有着先天的优势。只有那些在客户端解决不了的问题,比如和某个远程数据库交互,这时就应该使用CGI了。
SSI:一种用来动态输出HTML文本的特殊程序。
网页里包含有某个变量,提交给服务器后,只有该变量改变。此时我们希望服务器不要把整个页面内容都发送过来,而只需要告诉客户端的浏览器,哪个变量的值便成什么样了,浏览器会自动更新。
SSI在服务器端运行。
SSI不需要外部接口,它不像CGI从标准输入接收信息。
你浏览你的HTML文档时看不到SSI标记,因为它已经被相应的程序输出所替代。
所有的SSI命令都是嵌入在普通的HTML注释行中的。当服务器无法解释SSI时,它将不解释并直接把文档传给浏览器,由于命令在注释中,故浏览器将忽略它们。而当服务器识别SSI时,它并不将该命令传给浏览器,相反,服务器将从上到下扫描HTML文档,执行每一个嵌入注释的命令,并将命令的执行结果代替原注释。
注释文本— >。服务器将根本不查看注释,除非已启动SSI。
与纯注释不同的是,所有的SSI命令都是以#打头。
,command指出服务器做什么,tagname指出参数类型,parameter是该命令的用户定义值。
The current date is,服务器将向浏览器输出时间。
七、CGI编程入门–GET与POST示例
下面就GET和POST方法的应用,做一个小小的demo,给刚学习CGI编程的新手提供一点感性认识!
GET方法:做一个加法运算,需要接收两个参数
#include
#include
int main(void)
{
char *data;
char a[10],b[10];
printf(“Content-Type:text/html\n\n”);
printf(“\n”);
printf(“\n
printf(“\n”);
printf(“
data = getenv(“QUERY_STRING”);
if(sscanf(data,”a=%[^&]&b=%s”,a,b)!=2){
printf(“
}
else{
printf(“
}
printf(“
“);
printf(““);
printf(”
printf(“\n”);
printf(“\n”);
return 0;
}
POST方法:做一个乘法运算,需要接收两个参数
——————————–
#include
#include
int main(void){
int len;
char *lenstr,poststr[20];
char m[10],n[10];
printf(“Content-Type:text/html\n\n”);
printf(“\n”);
printf(“\n
printf(“/n”);
printf(“
lenstr=getenv(“CONTENT_LENGTH”);
if(lenstr == NULL)
printf(“
else{
len=atoi(lenstr);
fgets(poststr,len+1,stdin);
if(sscanf(poststr,”m=%[^&]&n=%s”,m,n)!=2){
printf(“
}
else{
printf(“
}
}
printf(“
“);
printf(““);
printf(“\n”);
printf(“\n”);
printf(“\n”);
fflush(stdout);
return 0;
}
再附上html测试文件cgi.html:
——————————–
Method: GET
please input two number:
|
Method: POST
please input two number:
|
简要说明:
(1) printf(“Content-Type:text/html/n/n”);
此行通过标准输出将字符串″Contenttype:text/plain/n/n″传送给Web服务器。它是一个MIME头信息,它告诉Web服务器随 后的输出是以纯ASCII文本的形式。请注意在这个头信息中有两个换行符,这是因为Web服务器需要在实际的文本信息开始之前先看见一个空行。
(2) data = getenv(“QUERY_STRING”);
CGI定义:当GET方法提交的表单被发送到服务器断后,表单中的数据被保存在服务器上一个叫做QUERY_STRING的环境变量中。这种表单的处理相对简单,只要读取环境变量就可以了。
(3) sscanf(data,”a=%[^&]&b=%s”,a,b)!=2
这个是关于sscanf函数的使用问题,自己可以上网搜索一下,这里不再详述!
(4)atoi(a)+atoi(b)
atoi函数的功能是将字符型成整型,只有转换之后才可以进行加法运算!
(5) lenstr=getenv(“CONTENT_LENGTH”);
Web服务器在调用使用POST方法的CGI程序时设置此环境变量,它的文本值表示Web服务器传送给CGI程序的输入中的字符数目,因此需要使用函数atoi() 将此环境变量的值转换成整数,并赋给变量len(下面有定义)。
(6) fgets(poststr,len+1,stdin);
这个是关于fgets函数的使用问题,自己可以上网搜索一下,这里不再详述!
其他cgi相关的博客:
c语言写CGI程序:http://www.voidcn.com/article/p-alghqkwy-hd.html
cgi的ppt教程: http://download.csdn.net/detail/kaloha3/5034831
服务器
客户端
CGI程序
HTTP通信
标准输入输出
(环境变量)
关于CGI的编程,我也还是新手!但只要懂C,则基于C的CGI编程就不会很难!
下面就GET和POST方法的应用,做一个小小的demo,给刚学习CGI编程的新手提供一点感性认识!
文件get.c如下:
——————————-
#include
#include
int main(void)
{
char *data;
char a[10],b[10];
printf(“Content-Type:text/html\n\n”);
printf(“\n”);
printf(“\n
printf(“\n”);
printf(“
data = getenv(“QUERY_STRING”);
if(sscanf(data,”a=%[^&]&b=%s”,a,b)!=2){
printf(“
}
else{
printf(“
}
printf(“
“);
printf(““);
printf(“
\n”);
printf(“\n”);
printf(“\n”);
return 0;
}
文件post.c如下:
——————————–
#include
#include
int main(void){
int len;
char *lenstr,poststr[20];
char m[10],n[10];
printf(“Content-Type:text/html\n\n”);
printf(“\n”);
printf(“\n
printf(“/n”);
printf(“
lenstr=getenv(“CONTENT_LENGTH”);
if(lenstr == NULL)
printf(“
else{
len=atoi(lenstr);
fgets(poststr,len+1,stdin);
if(sscanf(poststr,”m=%[^&]&n=%s”,m,n)!=2){
printf(“
}
else{
printf(“
}
}
printf(“
“);
printf(““);
printf(“\n”);
printf(“\n”);
printf(“\n”);
fflush(stdout);
return 0;
}
再附上html测试文件cgi.html:
——————————–
Method: GET
please input two number:
|
Method: POST
please input two number:
|
WordPress database error: [Table 'yf99682.wp_s6mz6tyggq_comments' doesn't exist]SELECT SQL_CALC_FOUND_ROWS wp_s6mz6tyggq_comments.comment_ID FROM wp_s6mz6tyggq_comments WHERE ( comment_approved = '1' ) AND comment_post_ID = 1634 ORDER BY wp_s6mz6tyggq_comments.comment_date_gmt ASC, wp_s6mz6tyggq_comments.comment_ID ASC