关于CGI

缘起

关于web开发的服务器端的编程的技术,个人了解的有ASPJSPPHP等系列的脚本语言。ASP使用IISJSP使用TomcatApachePHP之类的脚本语言使用ApacheCGI。这里关于CGI的认识有点模糊,尤其是决定学习RubyRails时,频频能看到CGI这个词。十分好奇,CGI到底为何物,搜索了一番。

1. CGI

1.1. 历史

最初,CGI是在1993年由美国国家超级电脑应用中心NCSA)为 NCSA HTTPd Web 服务器(httpsqlite一样,都是公公域软件,针对httpd补丁的汇总构成了最初的Apache)开发的。Httpd Web服务器使用了UNIX shell 环境变量来保存从 Web 服务器传递给CGI的参数,然后生成一个运行 CGI 的独立的进程

1.2. 简介

公共网关接口CGI(Common Gateway Interface)WWW技术中最重要的技术之一,其规范的地址为

http://www.ietf.org/rfc/rfc3875CGI是外部应用程序CGI程序)与Web服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的规程。CGI规范允许Web服务器执行外部程序,并将它们的输出发送给Web浏览器CGI运行在网络服务器上。CGI程序可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量,如php,perl,tcl等。

大多数CGI程序用来处理和解释来自表单的输入信息,并在服务器进行相应的处理,或将相应的信息反馈给浏览器CGI程序使网页具有交互功能。

1.3. CGI处理流程

简单来说:CGI可以理解为一个很简单的远程脚本调用。在服务器端有许多的脚本,这些脚本可以使用任何可执行语言编写(shellrubyperlPHP),然后用户通过url访问web服务器,服务器会根据已有的url mapping找到对应的一个脚本,然后执行这个脚本。最后把脚本执行的结果按照既定的格式(比如Htmlxmljson之类的)返回给用户。

CGI的简单处理流程:1.用户点击URL发送请求给web服务器 2.web服务器接受请求转交CGI程序 3.CGI程序把处理结果传送给web服务器 4.web服务器把结果发给到用户。这个处理流程就是著名的请求/响应模型,web开发都要遵守这个模型。

上述步骤中web服务器接受请求转交CGI程序,需要配置web服务器,将对因的URL请求映射为CGI程序(大多为脚本程序)。

每次CGI请求都要生成一个进程来运行,大量请求就会压垮服务器。对脚本语言而言,每次请求都重新载入和初始化解释器,开销太大。此时,可以将脚本语言直接集成到web服务器中(例如,Apache中的mod_perl,mod_php,mod_python,mod_ruby)。CGI相关的Apache模块:mod_actions(CGI脚本类型),mod_cgi(启动CGI并维护相关事件出错日志),mod_cgid,mod_env(设置CGI编译器的环境变量,比如软件库)

1.4. CGI环境变量

CGI实际通过Shell环境变量来获取相应的参数,一些常用的环境变量如下:

服务器类变量:

SERVER_NAME:运行CGI序为机器名或IP地址。

GETWAY_INTERFACECGI程序的版本,在UNIX下为 CGI/1.1

SERVER_INTERFACEWWW服务器的类型,如:CERN型或NCSA型。

请求类变量:

SERVER_PROTOCOL:通信协议,应当是HTTP/1.0

SERVER_PORTTCP端口,一般说来web端口是80

REQUEST_METHODHTTP方法名,常用的有GETPUTDELETEPOST

PATH_INFO浏览器用GET方式发送数据时的附加路径前缀

PATH_TRANSLATED:根据PATH_INFO指定的服务器上实际路径名。

SCRIPT_NAMECGI程序的相对路径名,比如/cgi-bin/script.cgi

QUERY_STRINGURL中问号后的内容,通过GET方法提交的表单输入的数据,格式为name=value,以&分隔

REMOTE_HOST:客户端的主机名,不能确定该值。

REMOTE_ADDR:客户端的IP地址。

REMOTE_USER:客户端的人名,用作某些权限类型

CONTENT_TYPE:使用PUTPOST发送的因特网媒体数据,通过HTTP包头提供

CONTENT_LENGTHPOSTPUT提交的数据的大小,由HTTP包头提供

HTTP_ACCEPT, HTTP_ACCEPT_LANGUAGE, HTTP_USER_AGENT, HTTP_COOKIE以及其他相关的变量包含HTTP包头中对应的数据。

HTTP_ACCEPTHTTP定义的浏览器能够接受的数据类型。

HTTP_REFERER:发送表单的文件URL。(并非所有的浏览器都传送这一变量)

HTTP_USER_AGENT:发送表单的浏览器的有关信息。

CGI部署的约定:

1.cgi-bin目录作为所有CGI程序的根目录 

2.扩展名约定:.cgi的文件为CGI脚本。

1.5. CGI编程语言

CGI本身独立于任何编程语言,只要相应的语言可以运行在服务器上,CGI 程序可以用任何脚本语言或者是完全独立编程语言实现。除 Perl 外,Unix shell script, Python, Ruby, PHP, Tcl, C/C++, 和 Visual Basic 都可以用来编写 CGI 程序,但Perl被广泛用来编写CGI程序。

脚本语言灵活性和高效开发效率,可以快速开发CGI程序,同时可以完成非常多的任务。CGI中脚本语言介绍如下:

Perl

1987年,Larry Wall吸取Csedawk,内部集成正则表达式,瑞士军刀般的脚本语言。

PHP

1994年,Rasmus Lerdorf,个人网站开发,Perl程序,C重写,Zend Enginephp5

特点:

1.混合CjavaPerl,加自创语法

2.在执行动态网页上,比其他动态语言(Perl)速度快

3.拥有强大的功能,可替代CGI

4.支持主流数据库和操作系统

5.可以用C/C++扩展

优势:开源,免费,快捷,夸平台,高效,面向对象,图像处理

Ruby

1995年,吸收了SmalltalkPerlLisp等语言,是一个让程序员感到快乐的语言。

其他的就不介绍了,诸如Python这类的语言。

1.6. 进一步学习

CGI的执行程序的模式为fork & execute,即对每次请求都创建一个新的进程(fork系统调用),然后执行,这种方法容易实现,但效率差,难以扩展,面对大量请求,进程的大量建立和消亡使操作系统性能大大下降。此外,由于地址空间无法共享,也限制了资源重用。因而存在替代性的解决方案:

1.web服务器自己实现允许第三方软件在其中运行的扩展机制,比如Apache的扩展模块,NSAPI插件和ISAPI插件

2.FastCGI

3.Simple Common Gateway Interface SCGI

4.使用其他的动态网站架构,比如Java EE,在Java servlet容器中运行Java代码提供动态或静态内容,通过多线程来取代多进程。

CGI标准:http://www.w3.org/CGI/

一些免费的CGI书籍:

1.http://www.cgi101.com/book/

2.http://oreilly.com/openbook/cgi/

2. CGI变体

由于CGIfork&execute模型存在性能问题,因而存在一些CGI变体。罗列如下:

2.1. FastCGI

FastCGI官方地址:http://www.fastcgi.com/drupal/ FastCGICGI的增强版,致力于减少web服务器和CGI程序之间互动开销,从而使服务器可以同时处理更多的网页请求。

CGI

CGI中为每个请求创建新的进程不同,FastCGI使用持续的进程来处理一连串的请求。这些进程由FastCGI服务器管理,而不是web服务器。当请求到来时,web服务器把环境变量和页面请求通过一个socketFastCGI进程在服务器上)或者TCP connectionFastCGI进程在远程服务器上)传递给FastCGI进程。

FastCGI像是一个常驻(long-live)型的CGI,可以一直运行,一旦激活后,不必每次都要花费时间去fork进程(这是CGI最为人诟病的fork-and-execute 模式)。支持分布式的运算,FastCGI程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。

Apache中,FastCGI通过mod_fcgid模块或mod_fastcgi模块实现。

2.1.1. FastCGI处理流程

FastCGI处理的流程如下:

1Web服务器启动时载入FastCGI进程管理器(IIS ISAPIApache Module)

2FastCGI进程管理器自身初始化,启动多个CGI解释器进程(比如多个php-cgi)并等待来自Web服务器的连接

3、当客户端请求到达Web服务器时,FastCGI进程管理器选择并连接到一个CGI解释器。Web服务器将CGI环境变量和标准输入发送到FastCGI子进程(比如php-cgi

4FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web服务器。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web服务器中)的下一个连接。在CGI模式中,php-cgi在此便退出了

在上述情况中,使用CGI,每一个PHP页面请求都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。额外的好处,可以使用持续数据库连接(Persistent database connection)

2.1.2. 特点

优点:语言无关,独立安全的执行环境,支持诸多语言和服务器,独立web服务器内部架构

缺点:多进程,耗内存

2.1.3. 进一步学习

FastCGI官方网:http://www.fastcgi.com/drupal/ 中的文档。

2.2. SCGI-Simple Common Gateway Interface

Simple Common Gateway Interface (SCGI)是一个和HTTP Server交互的应用程序接口,作为CGI的替代选项。和FastCGI类似,但更易实现,且部分运行CGI操作连接到外部数据库。

2.2.1. 规范Specification

客户端通过允许传输8位的可靠流控制协议来连接到SCGI服务器。客户端通过发送请求开始,但SCGI服务器看到请求结束后,返回一个相应并关闭连接。请求格式如下,相应的格式在规范中没有定义。

请求格式

请求由一组头部和一个主体(body)组成,头部的格式如下:

headers ::= header*

header ::= name NUL value NUL

name ::= notnull+

value ::= notnull*

notnull ::= <01> | <02> | <03> | … | <ff>

NUL = <00>

头部不允许出现重复字符串,第一个头部的name必须为CONTENT_LENGTHvaluebody的长度。即使value0,也必须有要CONTENT_LENGTHSCGI这两个头部,为了操作CGI转换,标准CGI的环境变量也必须在头部提供。

头部编码为网络字符串(netstring[len]":"[string]","格式)并发送给服务器应用程序,body随后发送,其长度由CONTENT_LENGTH头指定。

样例

web 服务器(SCGI客户端)打开一个连接并发送如下字符串连接:

"70:"

    "CONTENT_LENGTH" <00> "56" <00>

    "SCGI" <00> "1" <00>

    "REQUEST_METHOD" <00> "POST" <00>

    "REQUEST_URI" <00> "/deepthought" <00>

","

"What is the answer to life, the Universe and everything?"

Web应用程序(SCGI 服务器)发送如下相应结束关闭链接:

"Status: 200 OK" <0d 0a>

"Content-Type: text/plain" <0d 0a>

"" <0d 0a>

"42"

2.2.2. 实现

服务器实现:Apache Http ServerSCGI模块、LighttpdNginxIISISAPI SCGI扩展

语言接口:Haskell, Java, Lisp, Perl,PHP, Python, Ruby, Tcl

2.2.3. 进一步学习

SCGI规范:http://www.python.ca/scgi/protocol.txt

Perl SCGI interface

Java SCGI connector

Haskell SCGI package

Nginx SCGI Module

Tcl SCGI module

IIS SCGI extension

Apache SCGI modules and Python SCGI interface

3. PSGI

Perl web server Gateway Interface,简称PSGI,是web服务器和基于Perlweb应用程序和框架的接口,用来编写可移植的应用程序(单独运行或使用CGIFastCGImod_perl等)。项目灵感来自PythonWSGIWeb Server Gateway Interface),RubyRackJavaScriptJSGI

PSGI的应用程序是Perl子程序,它接受单个哈希表参数,返回包含三个元素的数组(HTTP状态码,HTTP头数组的引用,HTTP body行数组的引用)。其中HTTP body用来生成HTML文档。

PlackPSGI的一个实现,其支持的Perl框架很多(参见参考资料8)。

3.1. 样例

PSGIhello world程序hello.psgi

my $app = sub {

    return [200, ['Content-Type' => 'text/plain'], ["hello, world\n"]];

}

运行命令:plackup hello.psgi

3.2. 进一步学习

PSGI规范:Perl Web Server Gateway Interface Specification

Catalyzed上关于PlackNginx的文章:http://www.catalyzed.org/2009/11/mtplack-on-nginx-love.html

4. WSGI

Web Server Gateway Interface,中文名Web服务器网管接口,简称WSGI,是为Python定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。自从WSGI被开发出来以后,许多其它语言中也出现了类似接口(比如Perl中的PSGIRuby中的Rack)。

4.1. 缘由

以前,如何选择Python框架是一个问题。Web框架的选择会限制web服务器的选择,反之亦然。WSGI出现之前,Python应用程序通常为CGIFastCGImod_python甚至特定web服务器设计的。

WSGI是服务器(web服务器)与应用程序之间的一个低级别接口,提供开发可移植web应用。WSGI是基于CGI标准的,所以可以套接到CGI上。

简单来看,WSGI就是服务器与应用程序之间的中间件,他对于服务器来说,就是应用程序,对于应用程序来说就是服务器,在中间做中转处理,比如,在requestresponse上做修改。

4.2. 规范概览

WSGI有两方:服务器网关一方,以及应用程序应用框架一方。服务方调用应用方,提供环境信息,以及一个回调函数(提供给应用程序用来将消息头传递给服务器方),并接收Web内容作为返回值。

WSGI中间件同时实现了API的两方,因此可以在WSGI服务和WSGI应用之间起调解作用:从WSGI服务器的角度来说,中间件扮演应用程序,而从应用程序的角度来说,中间件扮演服务器。中间件组件可以执行以下功能:

  • l 根据目标URL,将请求消息路由到不同的应用对象。
  • l 允许在一个进程中同时运行多个应用程序或应用框架。
  • l 负载均衡和远程处理,通过在网络上转发请求和响应消息。
  • l 进行内容后处理,例如应用XSLT样式表。

4.3. 实例

Python语言写的符合WSGIHello World应用程序如下所示:

def app(environ, start_response):

    start_response('200 OK', [('Content-Type', 'text/plain')])

    yield "Hello world!\n"

代码解释:

第一行定义了一个名为appcallable,接受两个参数,environstart_responseenviron是包含了CGI中的环境变量的字典,start_response也是一个callable,接受两个必须的参数,statusHTTP状态)和response_headers(响应消息的头)。

第二行调用了start_response,状态指定为“200 OK”,消息头指定为内容类型是“text/plain”

第三行将响应消息的消息体返回

4.4. 进一步学习

WSGI维基百科:.http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface

Web服务器网关接口

关于WSGIWiki网站(英文)

WSGI教程(英文)

PEP 3333 -- Python Web Server Gateway Interface v1.0.1

WSGI metaframework啄木鸟关于wsgi的介绍

化整為零的次世代網頁開發標準: WSGI

5. Rack

Rack提供最小的,模块化的,可配性接口来开发Rubyweb应用程序。通过以最简方法包装HTTP请求和响应,it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.

Rack已经被用到所有的Ruby web框架和库,比如Ruby on RailsSinatra。可以通过Ruby Gem进行安装。

5.1. 简介

Rack就是RubyWSGI,是在服务器与应用程序提供一个中间件。通过截获用户发来的请求和应用程序以既定形式返回的数据,然后作出相应的处理。例如,一个用户的请求到来后,验证用户的访问url是否有效,或者验证用户的身份等。

作为一个中间件,rack的主要作用体现在通用逻辑和实际业务逻辑的分离,在rack中加入通用的逻辑,而无需在实际业务程序中添加类似的功能。由于rack标准的普遍性,几乎所有的主流Ruby web框架(Ruby on RailsSinatra)都按照rack标准开发的模块,rack也为开发者提供了大量的api来简化开发。

5.2. 样例

Rack兼容的Hello world程序:

app = lambda do |env|

  body = "Hello, World!"

  [200, {"Content-Type" => "text/plain", "Content-Length" => body.length.to_s}, [body]]

end

run app

5.3. 进一步学习

Rack wiki

Rack documentation

Rack at Google Groups

Rack-compliant applications

Rack编程中文pdf文档:http://www.iteye.com/topic/605707

后记

写博客最重要的是确定主题,有了主题,可以收集资料,分析处理资料,整理成文。主题(topic)的来源有很多,看到的,听说的,想到的都可以衍生出主题。

写博客要明确读者,自己或是别人,要站在读者角度,多问自己几个问题,想说什么,怎么说,有用吗,有趣吗。

CGI程序没有开发过,但是,自己曾经安装过一个使用CGIPerl程序-Monitorix。写这篇博客不容易啊,前后花了两天的时候。不过,也了解了很多有趣的东西,CGILibwwwRack,其实我最感兴趣的是

参考文献

1.CGIWSGIRackhttp://blog.youkuaiyun.com/cherry_sun/article/details/7751452

2.CGI 百度百科:http://baike.baidu.com/subview/32614/12037322.htm

3.Wikipedia公共网关接口

4.Common Gateway Interface:http://en.wikipedia.org/wiki/Common_Gateway_Interface

5.Fast CGI百度百科:http://baike.baidu.com/view/641394.htm

6.Fast CGI 维基百科http://zh.wikipedia.org/wiki/FastCGI

7.Simple Common Gateway Interface:http://en.wikipedia.org/wiki/Simple_Common_Gateway_Interface

8.PSGI:http://en.wikipedia.org/wiki/PSGI

9.WSGI中文维基

10.化整為零的次世代網頁開發標準: WSGI

11.PHPhttp://baike.baidu.com/subview/99/5828265.htm

<think>好的,我现在需要回答用户关于CGI(通用网关接口)的问题。首先,我需要回顾用户提供的引用内容,特别是引用[4],因为用户直接提到了CGI。此外,其他引用中提到的WSGI和MVC可能也有相关性,但用户的问题集中在CGI上,所以我应该优先处理引用[4]的信息。 首先,我需要明确CGI的基本定义。根据引用[4],CGI是Common Gateway Interface的缩写,用于Web服务器和外部程序之间的通信。这应该是回答的核心部分。我需要解释CGI的作用,它是如何工作的,以及它在Web开发中的角色。 接下来,用户可能需要了解CGI的工作原理。根据引用[4],当客户端发送请求时,Web服务器通过CGI调用外部程序(如Perl、Python脚本),处理数据后返回响应。这部分需要详细说明流程,例如请求的传递过程、环境变量的使用、输入输出的处理方式等。 然后,我应该考虑CGI的优点和缺点。优点可能包括简单易用、跨平台、语言无关性。缺点可能涉及性能问题,如每次请求都启动新进程,资源消耗大,不适合高并发场景。这部分需要结合引用[4]的内容,可能还需要补充其他知识,比如CGI与FastCGI或WSGI的区别,但用户提供的引用中没有详细说明,所以可能需要简要提及。 用户提供的引用中还提到了WSGI(引用[1]和[2]),这是Python的Web服务器网关接口,可以对比一下CGI和WSGI的不同,但用户的问题集中在CGI,所以这部分可能作为扩展知识,放在相关问题里。同样,引用[5]提到的MVC模式可能与CGI的应用场景有关,但这里可能不需要深入,除非用户的问题涉及架构模式。 此外,用户示例中的快速排序部分展示了代码块的使用,因此在回答中如果有示例代码,应该用代码块展示,比如一个简单的CGI脚本。例如,用Python写一个打印"Hello World"的CGI脚本,并说明如何配置服务器运行它。 需要确保回答结构清晰,分点说明,如定义、工作原理、优缺点、示例应用等。同时,根据用户要求,生成相关问题,可能需要包括CGI的替代技术、性能优化、与WSGI的区别等。 现在,我需要检查引用内容是否足够支持回答。引用[4]提供了CGI的基本定义和工作流程,但可能不够详细。例如,关于环境变量和输入输出的处理,可能需要更具体的说明。不过用户提供的引用中没有更多细节,所以可能需要基于现有知识补充,但要确保准确。 最后,确保回答符合系统级指令:使用中文,数学表达式正确,引用标识自然添加。例如,在提到CGI的缺点时,可以引用[4]关于每次请求启动新进程的部分。 总结回答的结构: 1. CGI的定义和作用 2. 工作原理(处理流程) 3. 优点 4. 缺点 5. 示例代码(如Python CGI脚本) 6. 相关问题 在写作过程中,需要注意引用标识的位置,例如在提到CGI处理请求时添加[^4],在讨论性能问题时同样引用[^4]。 现在开始组织内容,确保每个部分都有引用支持,并且语言简洁明了。</think>### CGI(通用网关接口)详解 #### 1. CGI的定义与作用 CGI(Common Gateway Interface,通用网关接口)是早期Web开发中用于**连接Web服务器与外部程序**的标准协议。它允许服务器将用户请求(如表单提交)转发给脚本或程序处理,再将结果返回客户端。CGI实现了动态内容生成,突破了静态网页的限制。 #### 2. 工作原理 1. **请求接收**:客户端(浏览器)发送HTTP请求到Web服务器。 2. **进程启动**:服务器根据请求路径识别CGI程序,并**创建新进程**执行该程序[^4]。 3. **参数传递**:通过环境变量(如`QUERY_STRING`)或标准输入(`stdin`)传递请求参数。 4. **处理与响应**:CGI程序处理数据,生成HTML内容并通过标准输出(`stdout`)返回给服务器。 5. **结果返回**:服务器将结果封装为HTTP响应,发送回客户端。 #### 3. 优点 - **跨语言支持**:支持Perl、Python、C等任何能读写标准输入输出的语言。 - **简单易用**:无需复杂框架,编写脚本即可实现动态功能。 - **平台无关性**:可在不同操作系统和Web服务器上运行。 #### 4. 缺点 - **性能瓶颈**:每次请求需**创建新进程**,导致高并发时资源消耗大、响应慢。 - **扩展性差**:难以处理持久化连接或复杂会话管理。 - **安全性风险**:直接暴露脚本路径,可能引发路径遍历等漏洞。 #### 5. 示例代码(Python CGI脚本) ```python #!/usr/bin/env python3 import cgi # 设置响应头 print("Content-Type: text/html\n") # 获取表单参数 form = cgi.FieldStorage() name = form.getvalue("name", "World") # 生成HTML内容 print(f"<h1>Hello, {name}!</h1>") ``` #### 6. 配置与运行 1. 将脚本保存为`.cgi`文件(如`hello.cgi`)。 2. 放置到Web服务器的CGI目录(如Apache的`/var/www/cgi-bin/`)。 3. 设置脚本可执行权限:`chmod +x hello.cgi`。 4. 通过浏览器访问:`http://localhost/cgi-bin/hello.cgi?name=User`。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值