菜鸟笔记
提升您的技术认知

fastcgi-ag真人游戏

cgi

什么是cgi

cgi(common gateway interface)通用网关接口描述了客户端和服务器程序之间传输数据的⼀种标准,可以让⼀个客户端,从⽹⻚浏览器向执⾏在⽹络服务器上的程序请求数据。
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处理流程

web浏览器 web浏览器
| |
|1.http request |4.http response
| |
web服务器 web服务器
| |
|2.stdin |3.stdout,stderr
| |
启动cgi解析器 -> 加载配置 -> 连接其他服务器 -> 逻辑处理 -> 退出

  1. web服务器收到客户端(浏览器)的请求http request,启动cgi程序,并通过环境变量、标准输⼊传递 数据
  2. cgi进程启动解析器、加载配置(如业务相关配置)、连接其它服务器(如数据库服务器)、逻辑处理等
  3. cgi进程将处理结果通过标准输出、标准错误,传递给web服务器
  4. web服务器收到cgi返回的结果,构建http response返回给客户端,并杀死cgi进程

特点

  1. web服务器和cgi通过环境变量、标准输入、标准输出、标准错误互相传递数据。
  2. web服务器接受到多少个请求就创建多少个cgi子进程,处理完请求后退出子进程,fork-and-execute。
  3. 每个⼦进程都需要启动⾃⼰的解释器、加 载配置,连接其他服务器等初始化⼯作,这是cgi进程性能低下的主要原因。当⽤户请求⾮常多的 时候,会占⽤⼤量的内存、cpu等资源,造成性能低下。
  4. cgi使外部程序与web服务器之间交互成为可能。cgi程序运⾏在独⽴的进程中,并对每个web请求建 ⽴⼀个进程,这种⽅法⾮常容易实现,但效率很差,难以扩展。⾯对⼤量请求,进程的⼤量建⽴和消亡 使操作系统性能⼤⼤下降。此外,由于地址空间⽆法共享,也限制了资源重⽤。

环境变量

get请求它将数据打包放置在环境变量query_string中,可以通过getenv(“query_string”)函数获取数据。

环境变数 含义
auth_type 存取认证类型
content_length 由标准输⼊传递给cgi程序的数据⻓度,以bytes或字元数来计算
content_type 请求的mime类型
gateway_interfac e 服务器的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得到所有的信息,再没有信息⼤⼩的限制了。

fastcgi说明

什么是fastcgi

fastcgi(fast common gateway interface)快速通用网关接口,是通用网关接口cgi的改进。描述了客户端和服务器程序之间传输数据的⼀种标准。
fastcgi致⼒于减少web服务器与cgi程式之间互动的开销,从⽽使服务器可以同时处理更多的web请求。与为每个请求创建⼀个新的进程不同,fastcgi使⽤持续的进程来处理⼀连串的请求。这些进程由fastcgi进程管理器管理,⽽不是web服务器。
nginx服务⽀持fastcgi模式,能够快速⾼效地处理动态请求。⽽nginx对应的fastcgi模块为:ngx_http_fastcgi_module。
ngx_http_fastcgi_module模块允许将请求传递给fastcgi服务器。

处理流程

fastcig进程管理器:启动cgi解析器 -> 加载配置 -> 连接其他服务器 -> 进行循环

web浏览器
|1
web服务器
|2
fastcgi执行环境
|3
进入循环 -> 逻辑处理 -> 退出 -> 循环等待
|4
web服务器
|5
web浏览器

  1. web服务器启动时载⼊初始化fastcgi执⾏环境。例如iis、isapi、apache mod_fastcgi、nginx ngx_http_fastcgi_module、lighttpd mod_fastcgi。
  2. fastcgi进程管理器⾃身初始化,启动多个cgi解释器进程并等待来⾃web服务器的连接。启动fastcgi进程时,可以配置以ip和unix域socket两种⽅式启动。
  3. 当客户端请求到达web服务器时,web服务器将请求采⽤socket⽅式转发fastcgi主进程,fastcgi主进程选择并连接到⼀个cgi解释器。web服务器将cgi环境变量和标准输⼊发送到fastcgi⼦进程。
  4. fastcgi⼦进程完成处理后将标准输出和错误信息从同⼀socket连接返回web服务器。当fastcgi⼦进程关闭连接时,请求便处理完成。
  5. fastcgi⼦进程接着等待并处理来⾃web服务器的下⼀个连接。

fastcgi特点

  1. cgi是所谓的短⽣存期应⽤程序,fastcgi是所谓的⻓⽣存期应⽤程序。fastcgi像是⼀个常驻(long-live)型的cgi,它可以⼀直执⾏着,不会每次都要花费时间去fork⼀次(这是cgi最为⼈诟病的fork-and-execute模式)。
  2. fastcgi⼦进程完成处理后将标准输出和错误信息从同⼀socket连接返回web服务器。

进程管理器spawn-fcgi

什么是spawn-fcgi

nginx不能像apache那样直接执⾏外部可执⾏程序,但nginx可以作为代理服务器,将请求转发给后端服务器,这也是nginx的主要作⽤之⼀。其中nginx就⽀持fastcgi代理,接收客户端的请求,然后将请求转发给后端fastcgi进程。

由于fastcgi进程由fastcgi进程管理器管理,⽽不是nginx。这样就需要⼀个fastcgi进程管理器,管理我们编写fastcgi程序。

spawn-fcgi是⼀个通⽤的fastcgi进程管理器,简单⼩巧,原先是属于lighttpd的⼀部分,后来由于使⽤⽐较⼴泛,所以就迁移出来作为独⽴项⽬。

spawn-fcgi使⽤pre-fork模型,功能主要是打开监听端⼝,绑定地址,然后fork-and-exec创建我们编写的fastcgi应⽤程序进程,退出完成⼯作。fastcgi应⽤程序初始化,然后进⼊死循环侦听socket的连接请求。

spawn-fcgi源码包下载地址:http://redmine.lighttpd.net/projects/spawn-fcgi/wiki

fcgi开发套件

使⽤c/c 编写fastcgi应⽤程序,可以使⽤fastcgi软件开发套件或者其它开发框架,如fcgi。
fcgi下载地址:wget https://fossies.org/linux/www/old/fcgi-2.4.0.tar.gz

fastcig编译测试

nginx 设置

nginx需要在源码编译的时候加入fastcgi—module

location /test {
    fastcgi_pass 127.0.0.1:8001; 
    fastcgi_index test;
    include fastcgi.conf;
}

重新加载配置

/usr/local/nginx/sbin/nginx -s reload

测试代码

#include 
#include 
#include 
#include 
#include "fcgi_stdio.h"
int main(int argc, char *argv[])
{
  
    int count = 0;
    //阻塞等待并监听某个端⼝,等待nginx将数据发过来
    while (fcgi_accept() >= 0)
    {
  
        //如果想得到数据,需要从stdin去读,实际上从nginx上去读
        //如果想上传数据,需要往stdout写,实际上是给nginx写数据
        printf("content-type: text/html\r\n");
        printf("\r\n");
        printf("fast cgi hello!");
        printf("");
        //server_name:得到server的host名称
        printf("request number %d running on host %s\n",
          count, getenv("server_name"));
    }
    return 0;
}

编译启动

root@vm-0-16-ubuntu:/usr/local/nginx/sbin# lsof -i:8001
root@vm-0-16-ubuntu:/usr/local/nginx/sbin# cd /home/workplace/0voice_tuchuang/learn_test/
root@vm-0-16-ubuntu:/home/workplace/0voice_tuchuang/learn_test# gcc fastcgi_src.c -o fastcgi_src -lfcgi
root@vm-0-16-ubuntu:/home/workplace/0voice_tuchuang/learn_test# ldconfig
root@vm-0-16-ubuntu:/home/workplace/0voice_tuchuang/learn_test# spawn-fcgi -a 127.0.0.1 -p 8001 -f ./fastcgi_src
spawn-fcgi: child spawned successfully: pid: 5926
root@vm-0-16-ubuntu:/home/workplace/0voice_tuchuang/learn_test# lsof -i:8001
command    pid user   fd   type   device size/off node name
fastcgi_s 5926 root    0u  ipv4 15752309      0t0  tcp localhost:8001 (listen)
网站地图