6.1 CGI

HTTP协议早期设计是一个通信应答协议,服务器不记录任何状态。

简单来说如下: 客户端请求服务器上的abc.html,服务器给客户端返回abc.html,完事儿结束。

想象一下客户端如果持续请求abc.html 100次,那么服务器傻傻的提供100次,因为服务器根本不记录任何状态,所以你要了,我就给就是。

这样设计的好处是足够简单,但是显然不是那么合理。

但是WWW发展,需要HTTP协议有更加强大的功能,更多需要和服务器的交互。

打个比方,登录淘宝时,每个用户进入相同的页面,但是输入了不同的用户名和密码,然后提交到服务器。

提交到服务器之后,服务器需要对用户名和密码进行验证。这种提交,显然请求的不能是简单的请求一个文件资源,而应该是调用服务器的某个方法,某个函数。

这个功能可以通过CGI来实现。 CGI是一个可执行程序,它能响应用户的请求,这个可执行程序可以使用任何语言来编写。

6.1 .CGI

通用网关接口(Common Gateway Interface/CGI)描述了客户端和服务器程序之间传输数据的一种标准,可以让一个客户端,从网页浏览器向执行在网络服务器上的程序请求数据。CGI 独立于任何语言的,CGI 程序可以用任何脚本语言或者是完全独立编程语言实现,只要这个语言可以在这个系统上运行。Unix shell script, Python, Ruby, PHP, perl, Tcl, C/C++, 和 Visual Basic 都可以用来编写 CGI 程序。

最初,CGI 是在 1993 年由美国国家超级电脑应用中心(NCSA)为 NCSA HTTPd Web 服务器开发的。这个 Web 服务器使用了 UNIX shell 环境变量 来保存从 Web 服务器传递出去的参数,然后生成一个运行 CGI 的独立的进程。cgi的处理流程如下图所示:

  • step1. web 服务器收到客户端(浏览器)的请求Http Request,启动CGI程序,并通过环境变量、标准输入传递数据

  • step2. cgi进程启动解析器、加载配置(如业务相关配置)、连接其它服务器(如数据库服务器)、逻辑处理等

  • step3. cgi程将处理结果通过标准输出、标准错误,传递给web 服务器

  • step4. web 服务器收到cgi返回的结果,构建Http Response返回给客户端,并杀死cgi进程

web服务器与cgi通过环境变量、标准输入、标准输出、标准错误互相传递数据。

在遇到用户连接请求:

1 先要创建cgi子进程,然后cgi子进程处理请求。处理完事退出这个子进程:fork-and-execute

2 cgi方式是客户端有多少个请求,就开辟多少个子进程,每个子进程都需要启动自己的解释器,加载配置,连接其他服务器等初始化工作,这是cgi进程性能低下的主要原因。当用户请求非常多的时候,会大量的占用内存、cpu等资源。造成性能低下。

环境变量

GET请求,它将数据打包放置在环境变量QUERY_STRING中,CGI从环境变量QUERY_STRING中获取数据。常见的环境变量如下表所示:

环境变数 内容
AUTH_TYPE 存取认证类型。
CONTENT_LENGTH 由标准输入传递给CGI程序的数据长度,以bytes或字元数来计算。
CONTENT_TYPE 请求的MIME类型
GATEWAY_INTERFACE 服务器的CGI版本编号。
HTTP_ACCEPT 浏览器能直接接收的Content-types, 可以有HTTP Accept header定义.
HTTP_USER_AGENT 递交表单的浏览器的名称、版本 和其他平台性的附加信息。
HTTP_REFERER 递交表单的文本的 URL,不是所有的浏览器都发出这个信息,不要依赖它
PATH_INFO 传递给cgi程式的路径信息
QUERY_STRING 传递给CGI程式的请求参数,也就是用"?"隔开,添加在URL后面的字串。
REMOTE_ADDR client端的host名称
REMOTE_HOST client端的IP位址。
REMOTE_USER client端送出来的使用者名称。
REMOTE_METHOD client端发出请求的方法(如get、post)。
SCRIPT_NAME CGI程式所在的虚拟路径,如/cgi-bin/echo。
SERVER_NAME server的host名称或IP地址。
SERVER_PORT 收到request的server端口。
SERVER_PROTOCOL 所使用的通讯协定和版本编号。
SERVER_SOFTWARE server程序的名称和版本。

标准输入

环境变量的大小是有一定的限制的,当需要传送的数据量大时,储存环境变量的空间可能会不足,造成数据接收不完全,甚至无法执行CGI程序。因此后来又发展出另外一种方法:POST,也就是利用I/O重新导向的技巧,让CGI程序可以由STDIN和STDOUT直接跟浏览器沟通。

当我们指定用这种方法传递请求的数据时,web 服务器收到数据后会先放在一块输入缓冲区中,并且将数据的大小记录在CONTENT_LENGTH这个环境变数,然后调用CGI程式并将CGI程序的STDIN指向这块缓冲区,于是我们就可以很顺利的通过STDIN和环境变数CONTENT_LENGTH得到所有的资料,再没有资料大小的限制了。

总结:CGI使外部程序与Web服务器之间交互成为可能。CGI程式运行在独立的进程中,并对每个Web请求建立一个进程,这种方法非常容易实现,但效率很差,难以扩展。面对大量请求,进程的大量建立和消亡使操作系统性能大大下降。此外,由于地址空间无法共享,也限制了资源重用。

results matching ""

    No results matching ""