前言
读了三年的研究生,没有碰过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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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<br>", *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
上面输出分别对应下面三种类型
与服务器自身相关的环境的变量
|
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
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");