CGI(Common Gateway Interface)是能让webserver和CGI脚本共同处理客户的请求的协议。

它的协议定义文档是http://www.ietf.org/rfc/rfc3875

当中Webserver负责管理连接,传输数据,网络交互等。

至于CGI脚本就负责管理详细的业务逻辑。

Webserver的功能是将client请求(HTTP Request)转换成CGI脚本请求。然后运行脚本,接着将CGI脚本回复转换为client的回复(HTTP Response)。

CGI的脚本请求有两部分:请求元数据(request meta-variables)和相关的消息体(message-body)。

请求元数据

包括:

                               "AUTH_TYPE" | "CONTENT_LENGTH" |
"CONTENT_TYPE" | "GATEWAY_INTERFACE" |
"PATH_INFO" | "PATH_TRANSLATED" |
"QUERY_STRING" | "REMOTE_ADDR" |
"REMOTE_HOST" | "REMOTE_IDENT" |
"REMOTE_USER" | "REQUEST_METHOD" |
"SCRIPT_NAME" | "SERVER_NAME" |
"SERVER_PORT" | "SERVER_PROTOCOL" |
"SERVER_SOFTWARE" | scheme |
protocol-var-name | extension-var-name
 
以下一个一个看:
 
AUTH_TYPE是唯一标识了用户的认证方式,比方basic,Digest等
CONTENT_LENGTH是请求消息体的长度
CONTENT_TYPE是标识消息体的格式
GATEWAY_INTERFACE标识使用的CGI的版本号,比方CGI/1.1
PATH_INFO说明了解释CGI脚本的地址
PATH_TRANSLATED就是能够被訪问的cgi的路径。它相应CGI脚本的路径。比方
http://somehost.com/cgi-bin/somescript/this%2eis%2epath%3binfo
相应的PATH_INFO就是/this.is.the.path;info
QUERY_STRING 请求參数(GET的參数就是放在这个里面的)
REMOTE_ADDR标识client的ip地址
REMOTE_HOST标识的是client的域名
REMOTE_IDENT是发出请求的使用者标示,大多数服务端选择忽略这个属性
REMOTE_USER是使用者的合法名称
REQUEST_METHOD是请求方法,包含GET/POST/PUT/DELETE等
SCRIPT_NAME是脚本程序的虚拟路径。比方是/test/test.php
SERVER_NAME是WEBserver的域名
SERVER_PORT是WEBserverport名
SERVER_PROTOCOL是WEBserver与client的交互请求协议
SERVER_SOFTWARE发送给client的response的Webserver的标识。比方nginx/1.0.6

请求消息体

就是直接将client的请求消息体转发。将消息体放在stdin中传递给script的
 

相关知识点

參数传递

以下的问题就是webserver获取了http请求后。因为http请求是有分GET和POST等方法的。參数怎么传递给可运行程序呢?
比方GET方法,CGI程序就会从环境变量QUERY_STRING中获取数据。
POST呢?Webserver会通过stdin(标准输入)想CGI中传送数据的。而传送的数据长度就是放在CONTENT_LENGTH中的。
相应于HTTP请求。QUERY_STRING存放http的GET參数,stdin存放HTTP的BODY參数

如今流行的nginx+php的方法就是使用nginx(webserver)将请求变成cgi请求到php-cgi上,然后php-cgi进程运行php,将返回值变成cgi response返回给nginx。

nginx再将它变成http回复返回给client。

可是这里有个问题,cgi是单进程的,一个进程的生命期就仅仅是请求进来。处理。返回回复这几个阶段。可是webserver都是须要接受多个web请求的,这里就须要在后端开启多个cgi了。一般的cgiserver都会设置同意开启多少个cgi的数量的。

这里要明白一点,cgi是有分服务端和client的差别的,cgiclient是放在webserver一側,像nginx。apache这种webserver就已经是实现了这个client。

server端须要另外重新启动。像nginx+cgi+php这种配合就须要启动php-cgi服务,当然你也能够想到这种服务一定是以deamon的形式在后台执行,然后会fork出非常多个cgi进程。
 

复用

当然有人会问,cgi进程不能复用是个问题,为什么不呢。fastcgi出现就是攻克了这个问题。它的一个进程能够处理多个请求。这样速度当然就升上去了。然后另一种cgi是scgi(simple cgi),scgi和fastcgi相似,仅仅能说它定义的协议更简单(所以才叫做simple)。scgi的client是c写的,服务端是perl写的。
就最常见的nginx+cgi+php来说。要明白一点php中$_SERVER中获取的信息实际都是从cgi中获取的,当然这个和nginx中获取的client信息是一致的。另外因为cgi是有client和服务端的差别的,因此非常easy想到cgiclient须要使用tcp与client连接,每一个连接当然须要占用一个port,因此还是会有port限制的。所以从这个角度上说。并非cgi开的越多越好(当然6w的port限制是远远够的了)。
 

安全

关于开启的cgi安全问题。以前鸟哥就爆出了一个bug:http://www.laruence.com/2010/05/20/1495.html
有兴趣的读者能够看看。
 
还有cgiserver不是在监听port吗?怎么防止外网的请求运行cgi呢?我们一般的办法就是直接绑定在127.0.0.1的ip地址上。保证仅仅有本机才干訪问

參考文档:

http://www.lyinfo.net.cn/webclass/cgi/default.htm
http://blog.csdn.net/ablo_zhou/article/details/3634954
http://www.ietf.org/rfc/rfc3875

最新文章

  1. Basic Tutorials of Redis(7) -Publish and Subscribe
  2. UVA - 11235 Frequent values
  3. 在生产环境记录http请求参数
  4. POJ 3641 快速幂+素数
  5. 架设laravel
  6. 文本读写vs二进制读写
  7. Color 颜色码-英文名称-十六进制-RGB对照表
  8. TD数量不确定时如何让其宽度平均分布
  9. Android自定义组合控件内子控件无法显示问题
  10. 百度定位一直出现4.9E -324的问题解决方法
  11. eclipse下启动tomcat访问网址报404错误
  12. PHP编译报错
  13. Visual Studio 向工程中添加文件夹
  14. Django的STATIC_ROOT和STATIC_URL以及STATICFILES_DIRS
  15. 实习日记a
  16. 在城市后面加上省,市,区 以及将MySQL入库脚本封装成class
  17. 设置close
  18. python开发_thread_线程基础
  19. 高通msm mdm 总结
  20. js面向(基于)对象编程—类(原型对象)与对象

热门文章

  1. python jieba包用法总结
  2. ppp详解
  3. 汇编CMOS
  4. 在windows下安装flex和bison、GCC
  5. 【Luogu】P1410子序列(DP)
  6. java date类型和calendar类型区别
  7. PHP中使用GD库方式画时钟
  8. python结构语句(while,if)
  9. PEP8 Python编码规范(转)
  10. ORACLE RMAN增量备份经典理解