前言
读了三年的研究生,没有碰过web相关开发了。本科的三年的web开发经验都忘记完了。工作找好了,最近准备开始重新复习一下C和web相关的知识,以前做web开发的时候主要是主要是用PHP那几十个API来做系统开发,对PHP底层没有去学习过,最近打算从CGI出发,从本质上来了解一下web底层相关技术。
今天主要看了下面几个CGI入门的知识,还不错。
FastCGI实战:http://blog.csdn.net/huangyaoshifog/article/details/335433。
CGI入门:http://blog.csdn.net/conquerwave/article/details/7029864
CGI运行机制以及优缺点
CGI以可执行程序(例如exe)的形式,以独立进程运行在http服务器中。当http接受到请求,通过创建一个CGI进程,CGI通过标准输入输出IO同HTTP服务器之间进行交互,从而处理各种请求。处理完以后释放CGI进程。
CGI的优点:
-
CGI是以独立进程的方式来运行,所以如果一个CGI处理失败退出,不影响后面CGI处理,保证服务器的稳定性
-
CGI相对脚本来说,具有高安全性
CGI缺点:
-
CGI处理进程的创建开销较大,无法在高密度请求环境下使用。
-
相对脚本来说,编辑HTML比较麻烦
下面主要列一下CGI的基本环境变量,作为以后查询用吧。
基本环境变量
服务器与CGI程序交换信息的协作方式是通过环境变量实现的。无论什么请求,CGI程序总能在特定位置找到某些信息。无论环境变量怎样定义,总有一些变量有着特定含义。环境变量是一写保存用户信息的内存区。例如,所有的机器都有一个PATH环境变量,当在当前目录找布道文件时就要查找PATH变量。当服务器收到一个请求后,它首先要收集它能得到的所有相关信息,并把它放入内存。那么,服务器要收集什么信息呢?
-
关于服务器自身的详细信息
-
关于用户的信息信息
-
关于用户请求的信息
服务器不知道CGI程序到底需要那些信息,所以它把这些信息一起收集,那么如果有什么重要的东西就不会遗漏了。
环境变量的存储
在写C语言的时候完整的main函数的写法应该如下:
int main(int argc, char **argv, char **envp);
其中 argc表示参数个数,argv表示参数字符串,而这个envp就表示环境变量字符串。参数和环境变量都可以不止一个,所以,用指向字符串指针的指针来表示。
比如我们用C语言写了一个程序,运行在命令行下,带有2个参数
-
C:> cpfile.exe c:\test.txt d:\test.txt
-
argc=3;
-
argv[0] = "cpfile.exe";
-
argv[1] = "c:\test.txt";
-
argv[2] = "d:\test.txt";
在c语言中的stdlib.h中有一个extern char **environ; 或者extern char **_environ;的声明这个envp的参数实际上就是environ。
好,我们看看在cgi程序(其实就是一个C语言程序)里面怎么枚举这些环境变量
-
#include
-
#include
-
#include
-
-
#define MAX_CONTENT_LEN 1024
-
-
int main()
-
{
-
extern char **environ;
-
int nlen = 0;
-
int i;
-
char szContent[MAX_CONTENT_LEN];
-
char **penv;
-
char *req = NULL;
-
-
memset(szContent, 0, MAX_CONTENT_LEN);
-
-
printf("Content-type: text/html\n\n");
-
-
for ( penv = environ; *penv; penv++ )
-
printf("%s
", *penv);
-
return 0;
-
}
输出结果如下:
-
SERVER_SOFTWARE=lighttpd/1.4.28
-
SERVER_NAME=127.0.0.1
-
GATEWAY_INTERFACE=CGI/1.1
-
SERVER_PROTOCOL=HTTP/1.1
-
SERVER_PORT=3000
-
SERVER_ADDR=0.0.0.0
-
REQUEST_METHOD=GET
-
REDIRECT_STATUS=200
-
REQUEST_URI=/cgi/testEnv.cgi
-
REMOTE_ADDR=127.0.0.1
-
REMOTE_PORT=52218
-
CONTENT_LENGTH=0
-
SCRIPT_FILENAME=/home/gss/workspace_c/web/cgi/testEnv.cgi
-
SCRIPT_NAME=/cgi/testEnv.cgi
-
DOCUMENT_ROOT=/home/gss/workspace_c/web/
-
HTTP_HOST=127.0.0.1:3000
-
HTTP_CONNECTION=keep-alive
-
HTTP_CACHE_CONTROL=max-age=0
-
HTTP_USER_AGENT=Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4
-
HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
-
HTTP_ACCEPT_ENCODING=gzip,deflate,sdch
-
HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.8
-
HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.3
上面输出分别对应下面三种类型
与服务器自身相关的环境的变量
GATEWAY_INTERFACE
|
服务器遵守的CGI版本
|
SERVER_NAME
|
服务器的IP或名字
|
SERVER_PORT
|
主机的端口号
|
SERVER_SOFTWARE
|
服务器软件的名字
|
|
-
SERVER_NAME:127.0.0.1
-
SERVER_PORT:3000
-
GATEWAY_INTERFACE:CGI/1.1
-
SERVER_SOFTWARE:lighttpd/1.4.28
与客户端相关的环境的变量
服务器了解你的CGI程序,但它一定不知道你的客户机环境。正因为如此,同客户机有关的变量才是最重要的。因为它涉及到你的浏览器等等。
HTTP_ACCEPT
|
例出能被次请求接受的应答方式
|
HTTP_ACCEPT_ENCODING
|
列出客户机支持的编码方式
|
HTTP_ACCEPT_LANGUAGE
|
表明客户机可接受语言的ISO代码
|
HTTP_USER_AGENT
|
标明客户使用的软件
|
-
HTTP_ACCEPT:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
-
HTTP_ACCEPT_ENCODING:gzip,deflate,sdch
-
HTTP_ACCEPT_LANGUAGE:en-US,en;q=0.8
-
HTTP_USER_AGENT:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4
与请求相关的环境的变量
每次服务器受到的请求都不可能是一样的。这意味着有许多CGI程序必须注意的信息。这些与请求相关的信息包含有用户调用的信息,用户如何发送请求,以及作为请求的一部分传送了多少(什么)信息。这些对你的程序来说是非常重要的,因此我们将化些时间详细地讨论一下其中的一些变量。特别是下面写出的三个变量。这三个变量相当重要。
-
REQUEST_METHOD
-
QUERY_STRING
-
CONTENT_LENGTH
你必须熟悉这三个变量,因为它们用来表示数据是如何送到CGI程序的;然后你所要要做的事情就是在这三个变量里取出数据,进行下一步的编程。其他的一些变量的用处很多,你可以了解你的竞争对手正在调用你的程序,你可以辨别用户是否注册,或者你可以设置连接到你的CGI程序以便要求附加路径信息包含在请求之中----因此你不必猜测你的用户正在你的服务器的哪个页面上。
CONTENT_LENGTH
|
POST请求中向标准输入(STDIN)发送的字节数
|
QUERY_STRING
|
传送给CGI程序的URL的问号(?)之后的那一部分
|
REMOTE_ADDR
|
最终用户的IP或主机名
|
REMOTE_USER
|
如果用户合法,则是用户的组名
|
REQUEST_METHOD
|
作为HTTP的一部分请求而传送数据的方法,比如get。
|
SCRPT_NAME
|
运行的脚本名字
|
-
REQUEST_METHOD=GET
-
REDIRECT_STATUS=200
-
REQUEST_URI=/cgi/testEnv.cgi
-
REMOTE_ADDR=127.0.0.1
-
REMOTE_PORT=52218
-
CONTENT_LENGTH=0
-
SCRIPT_FILENAME=/home/gss/workspace_c/web/cgi/testEnv.cgi
-
SCRIPT_NAME=/cgi/testEnv.cgi
上面的参数都可以通过getenv函数进行获取
-
data = getenv("QUERY_STRING");
-
阅读(2616) | 评论(0) | 转发(0) |