热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c++CGI与phpfastCGI解释和用法

什么是CGICGI描述了客户端和服务器程序之间传输数据的⼀种标准,可以让⼀个客户端,从⽹⻚浏览器向执⾏在⽹络服务器上的程序请求数据。CGI只是一个接口规


什么是CGI
  • CGI描述了客户端和服务器程序之间传输数据的⼀种标准,可以让⼀个客户端,从⽹⻚浏览器向执⾏在⽹络服务器上的程序请求数据。
  • CGI只是一个接口规范或协议,它的实现和具体的编程语言相关。在2000年以前,CGI通用网关接口盛行,那个时候,Perl是编写CGI的主流语言,以至于一般的CGI程序都是Perl程序。如今,上古巫术Perl早已淡出人们视野,CGI这技术虽然通用,但是实则真正仍在应用的恐怕只有C/C++了。
  • 最初,CGI 是在 1993 年由美国国家超级电脑应⽤中⼼(NCSA)为 NCSA HTTPd Web 服务器开发的。这个web服务器使用了Unix Shell环境变量来保存从web服务器传递出去的参数,然后生成一个运行CGI的独立的进程

 

通用网关接口是什么意思

CGI 即 Common Gateway Interface,译作“通用网关接口”。初次听闻,略感疑惑,实则每个字眼都值得玩味。

common

通用,是一个显著特性。虽然我们听说过Java的Servlet,Python的WSGI。但其实Java、Python都是支持CGI的,不仅如此,其他我们所熟知的语言大多也支持。理论上来说,所有支持标准输出,支持获取环境变量的编程语言都能用来编写CGI程序。

早期的web服务器,只能响应浏览器发来的HTTP镜头资源请求,并将存储在服务器中的静态资源返回给浏览器。随着Web技术的发展,逐渐出现了动态技术,但是Web服务器并不能直接运行动态脚本。为了解决Web服务器与外部应用程序(CGI程序)之间的数据互通,于是出现了CGI(Common Gateway Interface)通用网关接口。简单理解,可以认为GUI就是Web服务器和运行其上的应用程序进行“交流”的一种约定

 

PS: 其实,脚本(script)并不一定就是脚本语言编写的。脚本描述的是一类程序的特征:为了完成某一任务,用程序实现批量执行一组常用逻辑的组合。凡是符合这一特征的程序都可称作脚本。当然,时至今日,脚本语言所编写的程序都可以称之为脚本程序,并且其内部逻辑也早已变得并不简单。

Gateway

Gateway,网关。通常意识中,网关一词更多的是硬件层面的概念,但其实与CGI的网关二字之含义也是不谋而合的。称CGI为软件网关也不为过

  • 网关,更形象的叫法是协议翻译机。通常与网关输入输出两端通信使用的是不同的协议。即一方是HTTP协议,另一方可能是其他协议,比如企业内部的自定义协议
  • CGI程序通常部署到Web服务器(比如Apache上),Web服务器然后调用CGI程序,关于CGI程序到底如何从Web服务器中获得输入,请继续阅读下一节 Interface。

 

请注意区分Web Server和后台Server。

Interface(接口)

Interface:Come On。又是一个被国人翻译烂掉的词汇。API(应用程序接口)的I是它,被译作“接口”。UI(用户界面)的I也是它,被译作“界面”。实际他们是同样的意思。我更喜欢“接口”一词。

  • 接口,确切而言是“接口协议”,熟悉网络的同学们,肯定都明白“协议”是什么。所谓协议,既是通信双方或多方都共识并遵守的一套规则。就像红灯停,绿灯行,上下车道靠右行。只有全国人民都遵守这个规则,交通才不会出什么乱子。实际上规定绿灯停,红灯行,上下车道靠左行可不可以呢?当然可以,英国日本都是靠左行的,关键是全国人民的认知要一致,这个共识很重要。

  • 举几个栗子:TCP/IP这类二进制协议,协议内容的描述是某某字节是干嘛滴,其取值范围是什么,不同取值又是什么含义。HTTP协议是字符协议,这类协议内容的描述就是第一行是啥,第二行是啥……,应该出现啥单词,表示啥意思

  • 其实不管是TCP/IP或是HTTP,都可以统称为“网络协议”,粗浅一点理解就是“描述报文内容详细语义的协议”。而“接口协议”却不然,它不会定义哪些字节该写什么,也不会定义字符的内容规范。CGI其实是构架在HTTP协议之上的。它描述的是另一个维度的共识标准

CGI与CGI程序

CGI是Web服务器和一个独立的进程之间的协议

  • 它会将HTTP请求Request的Header头设置进进程的环境变量,HTTP请求的Body正文设置成进程的标准输入
  • 进程的标准输出设置为HTTP响应Response,包含Header头和Body正文。

 

通过CGI接口,Web服务器就能够获取客户端传递的数据,并转交给服务器端的CGI程序处理,然后返回结果给客户端。

简单来说,CGI实际上是一个接口标准,而通常所说的CGI指代其实是CGI程序,也就是说实现了CGI接口标准的程序,只要编程语言具有标准输入、标准输出和环境变量,就可以用来编写CGI程序

  • CGI程序通常标准输入(stdin)和标准输出(stdout)进行数据的输入输出,此外CGI程序还通过环境变量来得到输入,操作系统提供了很多环境变量,它们定义了程序的执行环境,应用程序可以存取它们。
  • Web服务器和CGI接口又设置了一些环境变量,用来向CGI程序传递一些重要的参数。CGI的GET方法还通过环境变量QUERY_STRING向CGI程序传递Form表单中的数据。

对于一个CGI程序,主要的工作是从环境变量和标准输入中读取数据,然后处理数据,最后向标准输出中输出数据

  • 环境变量:环境变量中存储的叫做Request Meta-Variables,也就是比如QUERY_STRING、PATH_INFO之类的,这些都是由Web服务器通过环境变量传递给CGI程序的,CGI程序也是从环境变量中读取的。
  • 标准输出:中存放的往往是用户通过PUTS和POST提交的数据,这些数据也是由Web服务器传递过来的

输入,输出


Web服务器在接收到用户浏览器的HTTP请求,比如请求如下URL:

 

http://guodongxiaren.me/cgi-bin/helloworld.cgi

  • 1
  • 此时在Web服务器调用helloworld.cgi之前,会把各类HTTP请求中的信息以环境变量的方式写入OS。CGI程序本质上是OS上一个普通的可执行程序,它通常语言本身库函数来获取环境变量,从而获得数据输入
  • 除了环境变量外,另外一个CGI程序获取数据的方式是标准输入(stdin)。比如Post请求一个CGI的URL,那么POST的数据,CGI是通过标准输入来获取到的

而CGI如何构造出数据(比如HTML页面)返回给浏览器的呢?

  • 其实CGI本身只要向标准输出去写入数据即可。比如printf、cout,比如System.out.println,又比如print、echo等。因为Web服务器已经做了重定向,将标准输出重定向给Web服务器的与浏览器向链接的socket
  • 此时要注意的是,不要以为返回HTML页面,那么直接输出一段HTML代码就OK,注意,此时CGI的输出承担的是HTTP协议的响应部分,因此HTTP响应报头也要自己标准输出出来,比如:

cout<<"Content-Type:text/html\n\n"<<endl;

  • 1

注意最后要有两个换行符&#xff0c;这是必须有的。因为HTTP协议本身就是一个字符协议。它需要通过一个空行来区分哪里是报头&#xff0c;哪里是实体。在两个换行符&#xff08;即一个空行&#xff09;之后就可以愉快的输出HTML&#xff08;即实体部分&#xff09;了。

关于环境变量

GET请求&#xff0c;它将数据打包放置在环境变量QUERY_STRING中&#xff0c;CGI从环境变量QUERY_STRING中获取数据。

常⻅的环境变量如下表所示&#xff1a;
在这里插入图片描述

标准输入

环境变量的大小是由一定的限制的&#xff0c;当需要传送的数据量大时&#xff0c;存储环境变量的空间可能会不足&#xff0c;造成数据接收不完全&#xff0c;甚至无法执行CGI程序。

因此后来有发展处另一种方法&#xff1a;POST&#xff0c;也就是利用IO重新导向的技巧&#xff0c;让CGI程序可以由stdin和stdout直接跟浏览器沟通

当我们使用这种方法传递请求的数据时&#xff0c;web服务器收到数据后会先放在一块输入缓冲区中&#xff0c;并且将数据的大小记录在CONTENT_LENGTH这个环境变量&#xff0c;然后调用CGI程序的stdin指向这块缓冲区&#xff0c;于是我们就可以通过stdin和环境变量CONTENT_LENGTH得到所有的信息&#xff0c;就没有信息大小的限制了

封装

CGI编写Web程序虽然看似解析组装等操作十分繁琐&#xff0c;但其实都有很多第三方的封装来简化这些操作&#xff0c;高级语言的标准库基本都已经做了封装&#xff0c;而针对C&#43;&#43;则有一个还不错的第三方库Cgicc。

关于路由

CGI程序有一不大不小的缺陷&#xff0c;缺乏URL路由的功能&#xff0c;基本上一个CGI都是独立提供给外界访问&#xff0c;一个CGI就是独立的可执行程序。因此不仅CGI的URL比较丑陋&#xff0c;而且容易暴露真实路径

CGI一般只做上层目录的路由&#xff0c;而这只能交给Web服务器去配置。比如&#xff1a;http://app/hello.cgi 的app目录在物理OS的什么位置可通过Apache去配置。虽然理论上讲CGI程序也可以实现http://app/hello.cgi/abc/def 这种形式的路由。但是基本上没人这样做。

CGI处理流程小结

 

  • web服务器收到客户端&#xff08;浏览器&#xff09;的请求Http Request&#xff0c;启动CGI程序&#xff0c;并通过环境变量、标准输入传递数据
  • CGI进程启动解析器、加载配置&#xff08;比如业务相关配置&#xff09;、连接其他服务器&#xff08;比如数据库服务器&#xff09;、逻辑处理等
  • CGI进程将处理结果通过标准输出、标准错误&#xff0c;传递给web服务器
  • web服务器收到CGI返回的结果&#xff0c;构建Http Response返回给客户端&#xff0c;并杀死CGI进程

web服务器与CGI通过环境变量、标准错误、标准输出、标准错误相互传递数据。在遇到用户连接请求&#xff1a;

  • 先要创建CGI子进程&#xff0c;然后CGI子进程处理请求&#xff0c;处理完毕退出这个子进程&#xff1a;&#xff1a;fork-and-execute
  • CGI方式是客户端有多少个请求&#xff0c;就开辟多少个子进程&#xff0c;每个子进程都需要启动自己的解释器、加载配置、连接其他服务器等初始化工作&#xff0c;这是CGI进程性能低下的主要原因。当用户请求非常多的时候&#xff0c;会占用大量的内存、CPU等资源&#xff0c;造成性能低下

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

FastCGI

为什么会有FastCGI的出现

既然有这么多现成的库做了封装&#xff0c;那么理应用CGI编写Web的也不少才对。其实不然&#xff0c;这是因为CGI有一大硬伤&#xff1a;

  • 每次HTTP请求CGI&#xff0c;Web服务器都要启动一个新的进程去执行一个CGI程序&#xff0c;即颇具Unix特色的fork-and-execute。当用户请求量大的时候&#xff0c;这个fork-and-execute的操作会严重拖慢Web服务器的性能
  • 时势造英雄&#xff0c;FastCGI(简称FCGI)技术产生了&#xff0c;简单来说&#xff0c;本身上就是一个常驻内存的进程池技术。由调度器负责将传递过来的CGI请求发送给处理CGI的handler进程来处理。在一个请求处理完成之后&#xff0c;该处理进程不销毁&#xff0c;继续等待下一个请求的到来

当然FCGI其实也并不是什么惊世骇俗的创意&#xff0c;很容易联想到的解决思路。资源池是后台性能优化中的常见套路。Java发明的Servlet技术也是一种常驻内存的网关通信技术&#xff0c;只不过它采用的是多线程而非进程。

什么是FastCGI

快速通⽤⽹关接⼝(Fast Common Gateway Interface&#xff0f;FastCGI)是通⽤⽹关接⼝(CGI)的改进&#xff0c;描述了客户端和服务器程序之间传输数据的⼀种标准。

FastCGI致力于减少Web服务器与CGI程序之间互动的开销&#xff0c;从而使服务器可以同时处理更多的web请求。与为每个请求创建一个新的进程不同&#xff0c;FastCGI使用持续的进程来处理一连串的请求&#xff0c;这些进程有FastCGI进程管理器管理&#xff0c;而不是web服务器。

nginx服务支持FastCGI模式&#xff0c;能够高效的处理动态请求。⽽nginx对应的FastCGI模块为&#xff1a;ngx_http_fastcgi_module。ngx_http_fastcgi_module模块允许将请求传递给FastCGI服务器

FastCGI处理流程

 

  • Web服务器启动时载入初始化FastCGI执行环境。例如IIS、ISAPI、apache mod_fastcgi、ngx_http_fastcgi_module、lighttpd mod_fastcgi。
  • FastCGI进程管理器自身初始化&#xff0c;启动多个CGI解释器进程并等待来自Web服务器的连接。启动FastCGI进程时&#xff0c;可以配置以IP和Unix域socket两种方式启动
  • 当客户端请求到达web服务器时&#xff0c;web服务器将请求采用socket方式转发FastCGI主进程&#xff0c;FastCGI主进程选择并连接到一个CGI解析器。Web服务器将CGI环境变量和标准输入发送到FastCGI子进程
  • FastCGI⼦进程完成处理后将标准输出和错误信息从同⼀socket连接返回Web 服务器。当FastCGI⼦进程关闭连接时&#xff0c;请求便处理完成。
  • FastCGI⼦进程接着等待并处理来⾃Web 服务器的下⼀个连接。

由于FastCGI程序并不需要不断的产⽣新进程&#xff0c;可以⼤⼤降低服务器的压⼒并且产⽣较⾼的应⽤效率。它的速度效率最少要⽐CGI 技术提⾼ 5 倍以上。它还⽀持分布式的部署&#xff0c;即FastCGI 程序可以在web 服务器以外的主机上执⾏。

CGI就是所谓的短生存期应用程序&#xff0c;FastCGI是所谓的长生存期应用程序。FastCGI像是一个常驻型的CGI&#xff0c;它可以一直执行着&#xff0c;不会每次都要花费时间去fork一次。

展望

我们知道&#xff0c;CGI可以直接吐出一个html网页&#xff0c;也可以进行各种计算、逻辑处理任务。但随着各类web前后端技术的发展&#xff0c;以及大数据、高并发的Server使用场景越来越多。现代的CGI的用法&#xff0c;在发生变化。越来越多的任务从后端转移到前端&#xff0c;前端页面利用强大的JS承担起更多的责任。

  • CGI一般不再用于直接返回html页面&#xff0c;同时将复杂的计算、IO任务下沉到后端&#xff08;后端可以进一步进行路由转发&#xff0c;实现负载均衡&#xff09;。使CGI作为前后端之间的中间层。彼时CGI的职能是完成基本的鉴权以及数据交换。
  • Restful风格API的出现&#xff0c;让CGI获得了续命。CGI解析前端请求&#xff0c;再转发给对应后端&#xff1b;然后从后端取回数据&#xff0c;给前端返回XML或JSON。然后前端JS利用XML/JSON中的数据来进行填充。可以绘制出丰富的界面或用作他用。JS可以使用Ajax技术来向后台CGI发起数据请求。Ajax完成的是不需要刷新整个页面就可以加载后端数据&#xff08;比如从数据库中取出&#xff09;。
  • 当然实际工程应用中很少严格遵守Restful的学院派定义&#xff0c;比如URL资源使用名词&#xff0c;然后使用各个HTTP的方法&#xff08;GET、POST、PUT、DELETE等&#xff09;表示动词。
  • 除了FCGI外&#xff0c;还有SCGI&#xff08;Simple CGI&#xff09;&#xff0c;也是作为CGI的替代协议而产生的&#xff0c;但他与FCGI更像&#xff0c;另外&#xff0c;SCGI在每次完成HTTP应答之后都立即关闭HTTP连接&#xff0c;有点“用完即走”的意思。这个简单的协议更符合Restful API的理念需要。但是名气不大。



推荐阅读
  • .NetCoreWebApi生成Swagger接口文档的使用方法
    本文介绍了使用.NetCoreWebApi生成Swagger接口文档的方法,并详细说明了Swagger的定义和功能。通过使用Swagger,可以实现接口和服务的可视化,方便测试人员进行接口测试。同时,还提供了Github链接和具体的步骤,包括创建WebApi工程、引入swagger的包、配置XML文档文件和跨域处理。通过本文,读者可以了解到如何使用Swagger生成接口文档,并加深对Swagger的理解。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • 本文介绍了NetCore WebAPI开发的探索过程,包括新建项目、运行接口获取数据、跨平台部署等。同时还提供了客户端访问代码示例,包括Post函数、服务器post地址、api参数等。详细讲解了部署模式选择、框架依赖和独立部署的区别,以及在Windows和Linux平台上的部署方法。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
  • 导读:在编程的世界里,语言纷繁多样,而大部分真正广泛流行的语言并不是那些学术界的产物,而是在通过自由发挥设计出来的。和那些 ... [详细]
  • Imdevelopinganappwhichneedstogetmusicfilebystreamingforplayinglive.我正在开发一个应用程序,需要通过流 ... [详细]
author-avatar
mobiledu2502881767
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有