精华内容
下载资源
问答
  • CGI编程

    2020-05-13 22:13:57
    CGI编程 CGI简介 CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口,服务器和客户端之间的通信,是客户端的浏览器和服务器端的http服务器之间的HTTP通信。通过CGI接口,Web...

    CGI编程

    CGI简介

    CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口,服务器和客户端之间的通信,是客户端的浏览器和服务器端的http服务器之间的HTTP通信。通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。

    组成

    组成Cgi程序的是两部分,一部分是html页面,就是用户看到的东西。另一部分则是运行在务器上的程序。一般来说,我们先写html页面,再写程序

    原理

    一 什么是CGI

    CGI(The Common Gateway Interface):通用网关接口,定义web服务器和客户脚本进行信息交互的一系列标准。

    二 web浏览器

    ​ 为了了解CGI的概念,让我们来看看当我们单击一个超链接来浏览一个特定的web页或URL的时候,背后会发生什么事?

    (1)浏览器首先会链接HTTP web 服务器并且请求一个URL 页面;

    (2) WEB服务器将会解析这个URL并且查询请求的文件名,如果找到了请求文件服务器就会将这个文件发送回浏览器,否则发送回一个包含错误信息提示的页面指示你请求的是一个服务器并不包含的文件。

    (3)WEB浏览器将接受来自服务器端的响应,并且向发出请求的用户显示接收到的文件。

    ​ 然而,HTTP服务器也可能会以如何这种方式进行配置,那就是无论什么时候接受到对特定目录下的文件的请求,服务器不会将这个文件发送回客户端,而是它作为一个程序被服务器执行,并产生出输出发送回客户端浏览器进行显示。

    ​ CGI(The Common Gateway Interface)是一个标准化的协议,能够使应用程序(通常称为CGI程序或CGI脚本)同web服务器和客户端进行交互。CGI程序能够用 Python, PERL, Shell, C or C++等语言来实现。

    工作示意图

    img

    web服务器配置

    1、install apache2

    2、sudo a2enmod cgi

    3、sudo systemctl restart apache2

    第一个CGI脚本

    #!/bin/bash
    echo "Content-type:text/html"
    echo ""
    echo "CGI Bash Example"
    

    注意要更改执行权限

    chmod 755 or 777

    使用CGI实现计数器

    采用文件存储当前数据,每一次刷新都得到最新数据并实现+1功能写入文件,从而实现计数器功能。

    #include<stdio.h>
    #include<stdlib.h>
    int main(void)
    {
        FILE * fp;
        int counter;
        printf("Content-type: text/html\n\n");    //注
        if ((fp=fopen("counter.txt","rb+")) == NULL){
            puts("Failed in opening file.");
            exit(1);
        }
        fscanf(fp, "%d", &counter);
        printf("counter:%d",counter);
        counter++;
        rewind(fp);
        fprintf(fp,"%d",counter);
        fclose(fp);
        return 0;
    }
    

    在这里插入图片描述

    展开全文
  • Python CGI编程什么是 CGICGI 目前由 NCSA 维护,NCSA 定义 CGI 如下:CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP 服务器,提供同客户端 HTML 页面的接口。网页浏览为了更...

    Python CGI编程

    什么是 CGI

    CGI 目前由 NCSA 维护,NCSA 定义 CGI 如下:

    CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP 服务器,提供同客户端 HTML 页面的接口。

    网页浏览

    为了更好的了解 CGI 是如何工作的,我们可以从在网页上点击一个链接或 URL 的流程:

    1、使用你的浏览器访问 URL 并连接到 HTTP web 服务器。

    2、Web 服务器接收到请求信息后会解析 URL,并查找访问的文件在服务器上是否存在,如果存在返回文件的内容,否则返回错误信息。

    3、浏览器从服务器上接收信息,并显示接收的文件或者错误信息。

    CGI 程序可以是 Python 脚本,PERL 脚本,SHELL 脚本,C 或者 C++ 程序等。

    CGI架构图

    1752401-20191107102117009-1189592066.png

    Web 服务器支持及配置

    在你进行 CGI 编程前,确保您的 Web 服务器支持 CGI 及已经配置了 CGI 的处理程序。

    Apache 支持 CGI 配置:

    设置好CGI目录:

    1752401-20191107102153631-535742325.png

    所有的HTTP服务器执行 CGI 程序都保存在一https://www.xuanhe.net/个预先配置的目录。这个目录被称为 CGI 目录,并按照惯例,它被命名为 /var/www/cgi-bin 目录。

    CGI 文件的扩展名为 .cgi,python 也可以使用 .py 扩展名。

    默认情况下,Linux 服务器配置运行的 cgi-bin 目录中为 /var/www。

    如果你想指定其他运行 CGI 脚本的目录,可以修改 httpd.conf 配置文件,如下所示:

    1752401-20191107102215539-1255667449.png

    在 AddHandler 中添加 .py 后缀,这样我们就可以访问 .py 结尾的 python 脚本文件:

    1752401-20191107102238560-1025069451.png

    第一个CGI程序

    我们使用 Python 创建第一个 CGI 程序,文件名为 hello.py,文件位于 /var/www/cgi-bin 目录中,内容如下:

    1752401-20191107102259326-533681844.png

    文件保存后修改 hello.py,修改文件权限为 755:

    1752401-20191107102331250-1453956000.png

    以上程序在浏览器访问 http://localhost/cgi-bin/hello.py 显示结果如下:

    1752401-20191107102351099-890765574.png

    这个的hello.py脚本是一个简单的Python脚本,脚本第一行的输出内容"Content-type:text/html"发送到浏览器并告知浏览器显示的内容类型为"text/html"。

    用 print 输出一个空行用于告诉服务器结束头部信息。

    展开全文
  • CGI 编程

    2013-05-02 15:38:30
    通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。 组成CGI通信系统的是两部分:一部分是html页面,就是在用户端浏览器上显示的页面。另一部分则是运行...

    一.基本原理

    CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口。通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。

    组成CGI通信系统的是两部分:一部分是html页面,就是在用户端浏览器上显示的页面。另一部分则是运行在服务器上的Cgi程序。

    它们之间的通讯方式如下图:

    服务器

    客户端

    CGI程序

    HTTP通信

    标准输入输出

    (环境变量)

           服务器和客户端之间的通信,是客户端的浏览器和服务器端的http服务器之间的HTTP通信,我们只需要知道浏览器请求执行服务器上哪个CGI程序就可以了,其他不必深究细节,因为这些过程不需要程序员去操作。

           服务器和CGI程序之间的通讯才是我们关注的。一般情况下,服务器和CGI程序之间是通过标准输入输出来进行数据传递的,而这个过程需要环境变量的协作方可实现。

     

    1.    服务器将URL指向一个应用程序

    2.    服务器为应用程序执行做准备

    3.    应用程序执行,读取标准输入和有关环境变量

    4.    应用程序进行标准输出

     

    对于Windows系统而言,还可以通过profile文件进行数据传输(如ini文件),但在

    这里不做研究。

    环境变量在CGI中有着重要的地位!每个CGI程序只能处理一个用户请求,所以在激

    活一个CGI程序进程时也创建了属于该进程的环境变量。

     

    二.环境变量

           对于CGI程序来说,它继承了系统的环境变量。CGI环境变量在CGI程序启动时初始化,在结束时销毁。

           当一个CGI程序不是被HTTP服务器调用时,它的环境变量几乎是系统环境变量的复制。

    当这个CGI程序被HTTP服务器调用时,它的环境变量就会多了以下关于HTTP服务器、客户端、CGI传输过程等项目。

     

    与请求相关的环境变量

    REQUEST_METHOD

    服务器与CGI程序之间的信息传输方式

    QUERY_STRING

    采用GET时所传输的信息

    CONTENT_LENGTH

    STDIO中的有效信息长度

    CONTENT_TYPE

    指示所传来的信息的MIME类型

    CONTENT_FILE

    使用Windows HTTPd/WinCGI标准时,用来传送数据的文件名

    PATH_INFO

    路径信息

    PATH_TRANSLATED

    CGI程序的完整路径名

    SCRIPT_NAME

    所调用的CGI程序的名字

    与服务器相关的环境变量

    GATEWAY_INTERFACE

    服务器所实现的CGI版本

    SERVER_NAME

    服务器的IP或名字

    SERVER_PORT

    主机的端口号

    SERVER_SOFTWARE

    调用CGI程序的HTTP服务器的名称和版本号

    与客户端相关的环境变量

    REMOTE_ADDR

    客户机的主机名

    REMOTE_HOST

    客户机的IP地址

    ACCEPT

    例出能被次请求接受的应答方式

    ACCEPT_ENCODING

    列出客户机支持的编码方式

    ACCEPT_LANGUAGE

    表明客户机可接受语言的ISO代码

    AUTORIZATION

    表明被证实了的用户

    FORM

    列出客户机的EMAIL地址

    IF_MODIFIED_SINGCE

    当用get方式请求并且只有当文档比指定日期更早时才返回数据

    PRAGMA

    设定将来要用到的服务器代理

    REFFERER

    指出连接到当前文档的文档的URL

    USER_AGENT

    客户端浏览器的信息

           CONTENT_TYPE:application/x-www-form-urlencoded,表示数据来自HTML表单,并且经过了URL编码。

    ACCEPT:客户机所支持的MIME类型清单,内容如:”image/gif,image/jpeg”

     

    REQUEST_METHOD:它的值一般包括两种:POSTGET,但我们写CGI程序时,最后还要考虑其他的情况。

    1POST方法

    如果采用POST方法,那么客户端来的用户数据将存放在CGI进程的标准输入中,同时将用户数据的长度赋予环境变量中的CONTENT_LENGTH。客户端用POST方式发送数据有一个相应的MIME类型(通用Internet邮件扩充服务:Multi-purpose Internet Mail Extensions)。目前,MIME类型一般是:application/x-wwww-form-urlencoded,该类型表示数据来自HTML表单。该类型记录在环境变量CONTENT_TYPE中,CGI程序应该检查该变量的值。

    2GET方法

    在该方法下,CGI程序无法直接从服务器的标准输入中获取数据,因为服务器把它从标

    准输入接收到得数据编码到环境变量QUERY_STRING(或PATH_INFO)。

    GETPOST的区别:采用GET方法提交HTML表单数据的时候,客户机将把这些数

    据附加到由ACTION标记命名的URL的末尾,用一个包括把经过URL编码后的信息与CGI程序的名字分开:http://www.mycorp.com/hello.htmlname=hgq$id=1QUERY_STRING的值为name=hgq&id=1

    有些程序员不愿意采用GET方法,因为在他们看来,把动态信息附加在URL的末尾有

    URL的出发点:URL作为一种标准用语,一般是用作网络资源的唯一定位标示。

     

    环境变量是一个保存用户信息的内存区。当客户端的用户通过浏览器发出CGI请求时,服务器就寻找本地的相应CGI程序并执行它。在执行CGI程序的同时,服务器把该用户的信息保存到环境变量里。接下来,CGI程序的执行流程是这样的:查询与该CGI程序进程相应的环境变量:第一步是request_method,如果是POST,就从环境变量的len,然后到该进程相应的标准输入取出len长的数据。如果是GET,则用户数据就在环境变量的QUERY_STRING里。

    3POSTGET的区别

           GET方式接收的数据是有长度限制,而用 POST方式接收的数据是没有长度限制的。并且,以 GET方式发送数据,可以通过 URL的形式来发送,但 POST方式发送的数据必须要通过 Form才到发送。

    三.CGI程序实现步骤

    1.从服务器获取数据

    C语言实现代码:

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

     

    int get_inputs()

    {

    int length;

    char *method;

    char *inputstring;

     

    method = getenv(“REQUEST_METHOD”); //将返回结果赋予指针

    if(method == NULL)

        return 1;       //找不到环境变量REQUEST_METHOD

    if(!strcmp(method, ”POST”)) // POST方法

    {

        length = atoi(getenv(“CONTENT_LENGTH”)); //结果是字符,需要转换

        if(length != 0)

        {

            inputstring = malloc(sizeof(char)*length + 1) //必须申请缓存,因为stdin是不带缓存的。

            fread(inputstring, sizeof(char), length, stdin); //从标准输入读取一定数据

    }

    }

    else if(!strcmp(method, “GET”))

    {

        Inputstring = getenv(“QUERY_STRING”);   

        length = strlen(inputstring);

    }

    if(length == 0)

    return 0;

    }

    Perl实现代码:

    $method = $ENV{‘REQUEST_METHOD’};

    if($method eq ‘POST’)

    {

        Read(STDIN, $input, $ENV{‘CONTENT_LENGTH’});

    }

    if($method eq ‘GET’ || $method eq ‘HEAD’)

    {

        $input = $ENV{‘QUERY_STRING’};

    }

    if($input eq “”)

    {

    &print_form;

    exit;

    }

           PYTHON代码实现

    #!/usr/local/bin/python

    import cgi

    def main():

    form = cgi.FieldStorage()

     

    Python代码实现更简单,cgi.FieldStorage()返回一个字典,字典的每一个key就是变量名,key对应的值就是变量名的值,更本无需用户再去进行数据解码!

     

           获取环境变量的时候,如果先判断“REQUEST_METHOD”是否存在,程序会更健壮,否则在某些情况下可能会造成程序崩溃。因为假若CGI程序不是由服务器调用的,那么环境变量集里就没有与CGI相关的环境变量(如REQUEST_METHODREMOTE_ADDR等)添加进来,也就是说“getenv(“REQUEST_METHOD”)”将返回NULL

    2URL编码

    不管是POST还是GET方式,客户端浏览器发送给服务器的数据都不是原始的用户数据,而是经过URL编码的。此时,CGI的环境变量Content_type将被设置,如Content_type = application/x-www-form-urlencode就表示服务器收到的是经过URL编码的包含有HTML表单变量数据。

    编码的基本规则是:

    变量之间用“&”分开;

    变量与其对应值用“=”连接;

    空格用“+”代替;

    保留的控制字符则用“%”连接对应的16禁止ASCII码代替;

    某些具有特殊意义的字符也用“%”接对应的16进制ASCII码代替;

    空格是非法字符;

    任意不可打印的ASCII控制字符均为非法字符。

    例如,假设3HTML表单变量filenamee-mailcomments,它们的值对应分别为hellomike@hotmail.comI’ll be there for you,则经过URL编码后应为:

     

    filename=hello&e-mail=hello@hotmail.com&comments=I%27ll+be+there+for+you

     

     

    所以,CGI程序从标准输入或环境变量中获取客户端数据后,还需要进行解码。解码的过程就是URL编码的逆变:根据“&”和“=”分离HTML表单变量,以及特殊字符的替换。

    在解码方面,PYTHON代码实现是最理想的,cgi.FieldStorage()函数在获取数据的同时就已自动进行代码转换了,无需程序员再进行额外的代码编写。Perl其次,因为在一个现成的Perl库:cgi-lib.pl中提供了ReadParse函数,用它来进行URL解码很简单:

    require ‘cgi-lib.pl’;

    &ReadParse(*input);

     

    3CGI数据输出

    CGI程序如何将信息处理结果返回给客户端?这实际上是CGI格式化输出。

    CGI程序中的标准输出stdout是经过重定义了的,它并没有在服务器上产生任何的输出内容,而是被重定向到客户浏览器,这与它是由C,还是PerlPython实现无关。

    所以,我们可以用打印来实现客户端新的HTML页面的生成。比如,Cprintf是向该进程的标准输出发送数据,PerlPythonprint向该进程的标准输出发送数据。

    (1)    CGI标题

    CGI的格式输出内容必须组织成标题/内容的形式。CGI标准规定了CGI程序可以使用

    的三个HTTP标题。标题必须占据第一行输出!而且必须随后带有一个空行。

    标题

    描述

    Content_type  (内容类型)

    设定随后输出数据所用的MIME类型

    Location   (地址)

    设定输出为另外一个文档(URL

    Status     (状态)

    指定HTTP状态码

     

    MIME

    向标准输出发送网页内容时要遵守MIME格式规则:

    任意输出前面必须有一个用于定义MIME类型的输出内容(Content-type)行,而且随后还必须跟一个空行。如果遗漏了这一条,服务将会返回一个错误信息。(同样使用于其他标题)

    例如PerlPython

    print “Content-type:text/html\n\n”;  //输出HTML格式的数据

    print “<body>welcome<br>”

    print “</body>”

    C语言:

    printf( “Content-type:text/html\n\n”);

    printf(“Welcome\n”);

     

    MIME类型以类型/子类型(type/subtype)的形式表示。

    其中type表示一下几种典型文件格式的一种:

    TextAudioVideoImageApplicationMutipartMessage

    Subtype则用来描述具体所用的数据格式。

    Application/msword

    微软的Word文件

    Application/octet-stream

    一种通用的二进制文件格式

    Application/zip

    Zip压缩文件

    Application/pdf

    Pdf文件

    。。。。。。。。。。。。。。。。。。。。。。。。。。

    。。。。。。。。。。。。。。。。。。。。。。。。。

     

    Location

    使用Location标题,一个CGI可以使当前用户转而访问同一服务器上的另外一个程序,甚至可以访问另外一个URL,但服务器对他们的处理方式不一样。

    使用Location的格式为:LocationFilename/URL,例如:

    print “Location:/test.html\n\n”;

    这与直接链接到test.html的效果是一样的。

     

    print “Location:http://www.chinaunix.com/\n\n”

    由于该URL并不指向当前服务器,用户浏览器并不会直接链接到指定的URL,而是给用户输出提示信息。

     

     

    HTTP状态码:

           表示了请求的结果状态,是CGI程序通过服务器用来通知用户其请求是否成功执行的信息码,本文不做研究。

    四.CGI中的信号量和文件锁

           因为CGI程序时公用的,而WEB服务器都支持多进程运行,因此可能会发生同时有多个用户访问同一个CGI程序的情况。比如,有2个用户几乎同时访问同一个CGI程序,服务器为他们创建了2CGI程序进程,设为进程A和进程B。假如进程A首先打开了某个文件,然后由于某种原因被挂起(一般是由于操作系统的进程调度);而就在进程A被挂起的这段时间内,进程B完成了对文件的整个操作流程:打开,写入,关闭;进程A再继续往下执行,但进程A所操作的文件依旧是原来文件的就版本,此时进程A的操作结果将覆盖进程B的操作结果。

    为了防止这种情况发生,需要用到文件锁或者信号量。

    钥匙文件?

     

    假如有多个不同的HTML可以调用同一个CGI程序,那么CGI程序如何区分它们呢?一个是通过隐含的INPUT标签。不过觉得这个比较麻烦,因为CGI必须经过一系列解码后才能找到这个隐含INPUT的变量和其值。

    五.设置HTTP服务器以兼容CGI

           Perl编写的CGI程序后缀为:.plPython编写的CGI程序后缀为:.py;而C编写的CGI程序后缀为:.cgi,如果在win下编译出来的是.exe,最好将它重命名为.cgi。这些都是为了HTTP服务能够识别并调用它们。

           当使用appche httpd服务器时,请编辑它的配置文件httpd.conf如下:

           修改AddHandler cgi-script一句为AddHandler cgi-script .cgi .py .pl

    六.关于CGIC语言库——cgihtml

           Cgihtml是一个应用非常广泛的C语言编写的CGI库。它提供的功能函数如下:

           Read_cgi_input():获取并解析HTML表单输入,返回一个指向某结构体的指针

           Cgi_val():获取每个表单变量的值

           Html_header():输出HTML标题栏

           Html_begin():输出HTML文档的开始部分

           H1():输出一行字符,字体为H1

    Html_end():输出HTML文档的结尾部分。

    #include “cgi-lib.h”

    #include “html-lib.h”

    #include “string-lib.h”

    六.后话

    有的人认为可以用JavaScript来代替CGI程序,这其实是一个概念上的错误。JavaScript只能够在客户浏览器中运行,而CGI却是工作在服务器上的。他们所做的工作有一些交集,比如表单数据验证一类的,但是JavaScript是绝对无法取代CGI的。但可以这样说,如果一项工作即能够用JavaScript来做,又可以用CGI来做,那么绝对要使用JavaScript,在执行的速度上,JavaScriptCGI有着先天的优势。只有那些在客户端解决不了的问题,比如和某个远程数据库交互,这时就应该使用CGI了。

     

     

    SSI:一种用来动态输出HTML文本的特殊程序。

    网页里包含有某个变量,提交给服务器后,只有该变量改变。此时我们希望服务器不要把整个页面内容都发送过来,而只需要告诉客户端的浏览器,哪个变量的值便成什么样了,浏览器会自动更新。

    SSI在服务器端运行。

    SSI不需要外部接口,它不像CGI从标准输入接收信息。

    你浏览你的HTML文档时看不到SSI标记,因为它已经被相应的程序输出所替代。

    所有的SSI命令都是嵌入在普通的HTML注释行中的。当服务器无法解释SSI时,它将不解释并直接把文档传给浏览器,由于命令在注释中,故浏览器将忽略它们。而当服务器识别SSI时,它并不将该命令传给浏览器,相反,服务器将从上到下扫描HTML文档,执行每一个嵌入注释的命令,并将命令的执行结果代替原注释。

    <! –注释文本-- >。服务器将根本不查看注释,除非已启动SSI

    与纯注释不同的是,所有的SSI命令都是以#打头。

    <! --#command tagname = “parameter”-- >,command指出服务器做什么,tagname指出参数类型,parameter是该命令的用户定义值。

    The current date is<! --#echo var = “DATE.LOCAL”-- >,服务器将向浏览器输出时间。

     

     

    七、CGI编程入门--GET与POST示例

     

     


    关于CGI的编程,我也还是新手!但只要懂C,则基于C的CGI编程就不会很难!
    下面就GET和POST方法的应用,做一个小小的demo,给刚学习CGI编程的新手提供一点感性认识!

     

     


    GET方法:做一个加法运算,需要接收两个参数 

     

    文件get.c如下:
     
    -------------------------------
    #include <stdio.h>
    #include <stdlib.h>
    int main(void)
    {
            char *data;
            char a[10],b[10];
            printf("Content-Type:text/html\n\n");
            printf("<HTML>\n");
            printf("<HEAD>\n<TITLE >Get Method</TITLE>\n</HEAD>\n");
            printf("<BODY>\n");
            printf("<div style=\"font-size:12px\">\n");
            data = getenv("QUERY_STRING");
            if(sscanf(data,"a=%[^&]&b=%s",a,b)!=2){
                    printf("<DIV STYLE=\"COLOR:RED\">Error parameters should be entered!</DIV>\n");
            }
            else{
                   printf("<DIV STYLE=\"COLOR:GREEN; font-size:15px;font-weight:bold\">a + b = %d</DIV>\n",atoi(a)+atoi(b));
            }
            printf("<HR COLOR=\"blue\" align=\"left/" width=\"100\">");
            printf("<input type=\"button\" value=\"Back CGI/" οnclick=\"javascript:window.location='../cgi.html'/">");
            printf("
    \n");
            printf("</BODY>\n");
            printf("</HTML>\n");
            return 0;
    }
     


    POST方法:做一个乘法运算,需要接收两个参数 

     

    文件post.c如下:
    --------------------------------

    #include <stdio.h>
    #include <stdlib.h>
    int main(void){
            int len;
            char *lenstr,poststr[20];
            char m[10],n[10];
            printf("Content-Type:text/html\n\n");
            printf("<HTML>\n");
            printf("<HEAD>\n<TITLE >post Method</TITLE>\n</HEAD>\n");
            printf("<BODY>/n");
            printf("<div style= \"font-size:12px\">\n");
            lenstr=getenv("CONTENT_LENGTH");
            if(lenstr == NULL)
                    printf("<DIV STYLE=\"COLOR:RED\">Error parameters should be entered!</DIV>\n");
            else{
                    len=atoi(lenstr);
                    fgets(poststr,len+1,stdin);
                    if(sscanf(poststr,"m=%[^&]&n=%s",m,n)!=2){
                            printf("<DIV STYLE=\"COLOR:RED\">Error: Parameters are not right!</DIV>\n");
                    }
                    else{
                           printf("<DIV STYLE=\"COLOR:GREEN; font-size:15px;font-weight:bold\">m * n = %d</DIV>\n",atoi(m)*atoi(n));
                    }
            }
            printf("<HR COLOR=\"blue\" align=\"left\" width=\"100\">");
            printf("<input type=\"button\" value=\"Back CGI\" οnclick=\"javascript:window.location='../cgi.html'\">");
            printf("\n");
            printf("</BODY>\n");
            printf("</HTML>\n");
            fflush(stdout);
            return 0;
    }


     

    再附上html测试文件cgi.html:
    --------------------------------
    <html>
    <head>
    <title>CGI Testing</title>
    </head>
    <body>
    <table width="200" height="180" border="0" style="font-size:12px">
    <tr><td>
    <div style="font-weight:bold; font-size:15px">Method: GET
    <div>please input two number:<div>
    <form method="get" action="./cgi-bin/get">
    <input type="txt" size="3" name="a">+
    <input type="txt" size="3" name="b">=
    <input type="submit" value="sum">
    </form>
    </td></tr>
    <tr><td>
    <div style="font-weight:bold; font-size:15px">Method: POST
    <div>please input two number:<div>
    <form method="post" action="./cgi-bin/post">
    <input type="txt" size="3" name="m">*
    <input type="txt" size="3" name="n">=
    <input type="submit" value="resu">
    </form>
    </td></tr>
    <tr><td><inputtype="button" value="Back Home"οnclick='javascript:window.location="./index.html"'></td></tr>
    </table>
    </body>
    </html>

     


    简要说明:

     


    (1) printf("Content-Type:text/html/n/n");
    此行通过标准输出将字符串″Contenttype:text/plain/n/n″传送给Web服务器。它是一个MIME头信息,它告诉Web服务器随 后的输出是以纯ASCII文本的形式。请注意在这个头信息中有两个换行符,这是因为Web服务器需要在实际的文本信息开始之前先看见一个空行。

    (2) data = getenv("QUERY_STRING");
    CGI定义:当GET方法提交的表单被发送到服务器断后,表单中的数据被保存在服务器上一个叫做QUERY_STRING的环境变量中。这种表单的处理相对简单,只要读取环境变量就可以了。

    (3) sscanf(data,"a=%[^&]&b=%s",a,b)!=2
    这个是关于sscanf函数的使用问题,自己可以上网搜索一下,这里不再详述!

    (4)atoi(a)+atoi(b)
    atoi函数的功能是将字符型成整型,只有转换之后才可以进行加法运算!

    (5) lenstr=getenv("CONTENT_LENGTH");
    Web服务器在调用使用POST方法的CGI程序时设置此环境变量,它的文本值表示Web服务器传送给CGI程序的输入中的字符数目,因此需要使用函数atoi() 将此环境变量的值转换成整数,并赋给变量len(下面有定义)。

    (6) fgets(poststr,len+1,stdin);
    这个是关于fgets函数的使用问题,自己可以上网搜索一下,这里不再详述!


    展开全文
  • Cgi编程傻瓜书Cgi编程傻瓜书Cgi编程傻瓜书
  • 精通CGI编程 CGI

    热门讨论 2009-07-12 12:59:47
    精通CGI编程,CGI编程,CGI高级教程
  • Perl CGI编程

    2021-01-03 04:55:50
    Perl CGI编程 什么是CGI CGI 目前由NCSA维护,NCSA定义CGI如下: CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP服务器,提供同客户端HTML页面的接口。 网页浏览 为了更好的了解...
  • Ruby CGI 编程

    2021-01-03 04:36:47
    使用Ruby您不仅可以编写自己的SMTP服务器,FTP程序,或Ruby Web服务器,而且还可以使用Ruby进行CGI编程。 接下来,让我们花点时间来学习Ruby的CGI编辑。 网页浏览 为了更好的了解CGI是如何工作的,我们可以从在网页...
  • CGI编程学习

    2013-09-24 09:57:48
    CGI编程学习
  • CGI 编程基础

    2020-10-06 17:28:31
    记--CGI编程基础,CGI编程简单例子。 例子1:常用参数 例子2:GET、POST请求参数获取、文件上传 例子3:原生AJAXGET、POST请求 例子4:JQueryAJAXGET、POST请求 例子打包:...

                                                             CGI 编程基础

    一、简述

          记--CGI编程基础,CGI编程简单例子。

           例子1:常用参数

           例子2:GET、POST请求参数获取、文件上传

           例子3:原生AJAX GET、POST请求

           例子4:JQuery AJAX GET、POST请求

           例子打包:https://wwa.lanzous.com/iGkmLh7ycqb

    二、例子1--常用参数

    客户端IP:REMOTE_ADDR

    客户端浏览器信息:HTTP_USER_AGENT

    客户端请求方式:REQUEST_METHOD

    客户端语言版本:HTTP_ACCEPT_LANGUAGE

    获取GET参数:QUERY_STRING

    获取POST参数:CONTENT_LENGTH(内容长度)、CONTENT_TYPE(MIME类型)、CONTENT_FILE(文件名称)

    测试代码:

    /****************************************************************
     * Project:cgi_test
     * File name: cgi.c
     * Create on: 2020.09.14
     * Anthor: Genven_Liang
     * Description: cgi excample
     ****************************************************************/
    
    #include <stdio.h>
    #include <stdlib.h> //getenv
    
    int main(void)
    {	
    	/* 说明返回内容类型为html文本 */
    	printf("Content-Type:text/html\n\n");
    
    	/* 客户端IP */
    	char *client_ip = getenv("REMOTE_ADDR");
    
    	/* 客户端浏览器信息 */
    	char *user_agent = getenv("HTTP_USER_AGENT");
    
    	/* 请求方式 */
    	char *req_method = getenv("REQUEST_METHOD");
    
    	/* 客户端语言 */
    	char *client_language = getenv("HTTP_ACCEPT_LANGUAGE");
    
    	/* 返回数据给浏览器 浏览器一般只处理第一句printf (除printf("Content-Typexxx")) */
    	printf("client ip:%s<br/>request method:%s<br/>client language:%s<br/>user agent:%s", client_ip, req_method, client_language, user_agent);//<br/>是html的换行
    
    	return 0;	
    }

    测试结果:

    注:更多客户端信息请参考http请求首部:

     

    三、例子2: GET、POST请求参数获取、文件上传

    说明:在直接请求url是Get方式,参数直接在url后面添加,参数与url以'?'隔开,如:http://192.168.159.128/cgi-bin/test.cgi?参数

    链接也是get方式。form表单请求可以指定get方式或者是post方式。method="get"或method="post"

    使用form表单上传文件:设置enctype="multipart/form-data"

    测试代码:

    test.html文件

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title>CGI 例子2</title>
    	</head>
    
    	<body>
    		<a href="/cgi-bin/test.cgi?1234">Get请求</a>
    		<hr/>
    		<form action="/cgi-bin/test.cgi" method="get">
    			<label>用户名:</label><input type="text" name="userName"/></br>
    			<label>用户信息:</label><input type="text" name="userInfo"/></br>
    			<input type="submit" name="get_request" value="Get请求">
    		</form>
    		<hr/>
    		<form action="/cgi-bin/test.cgi" method="post" enctype="text/plain">
    			<label>用户名:</label><input type="text" name="userName"/></br>
    			<label>用户信息:</label><input type="text" name="userInfo"/></br>
    			<input type="submit" name="post_request" value="Post请求">
    		</form>
    		<hr/>
    		<form action="/cgi-bin/test.cgi" method="post" enctype="multipart/form-data">			
    			<input type="submit" name="post_file" value="上传文件">
    			<input type="file" name="file">
    		</form>
    	</body>
    </html>

    cgi.c文件

    /****************************************************************
     * Project:cgi_test
     * File name: cgi.c
     * Create on: 2020.09.14
     * Anthor: Genven_Liang
     * Description: cgi excample
     ****************************************************************/
    
    #include <stdio.h>
    #include <stdlib.h> //getenv
    #include <string.h>
    
    #define BUF_MAX_SIZE	(2*1024)
    #define FILE_BUF_MAX_SIZE	(4*1024)
    
    int main(void)
    {	
    	/* 说明返回内容类型为html文本 */
    	printf("Content-Type:text/html\n\n");
    
    	/* 请求方式 */
    	char *req_method = getenv("REQUEST_METHOD");
    
    	if (0 == strcmp("GET", req_method)) { /* 处理GET请求 */
    		char *get_arg = getenv("QUERY_STRING");//获取Get数据
    		if (NULL == get_arg) {
    			get_arg = "";
    		}
    		printf("get arguments:%s.", get_arg);
    	} else if (0 == strcmp("POST", req_method)) { /* 处理POST请求 */
    		char *content_len = getenv("CONTENT_LENGTH");//获取数据长度
    		char *content_type = getenv("CONTENT_TYPE");//获取数据类型 application/x-www-form-urlencoded、multipart/form-data、text/plain 其中:multipart/form-data是文件传输
    
    		int len = 0;
    		if (NULL != content_len) {
    			len = atoi(content_len);
    		}		
    
    		if (len > 0) { //获取post数据	
    			if (NULL != content_type && NULL == strstr(content_type, "multipart/form-data")) {//普通文本参数
    				char dat_buf[BUF_MAX_SIZE] = {0};
    				if (len > BUF_MAX_SIZE) {
    					len = BUF_MAX_SIZE;
    				}
    				len = fread(dat_buf, 1, len, stdin);
    				printf("post type:%s. len:%d, data:%s.", content_type, len, dat_buf);
    				//使用字符串分割函数获取各个参数:strtok_r
    			} else {//文件数据, boundary包含文件偏移量,大文件采用的是续传方式,会用到该参数,例子上传的是小文件,因此没有判断处理
    				//这里仅处理小文件不分包情况,大文件需要额外处理
    
    				//获取边界标识符
    				char *boundary = strstr(content_type, "boundary=");
    				if (NULL == boundary) {
    					printf("post-file find boundary error.");
    					return -1;
    				}
    				boundary += strlen("boundary=");
    
    				char file_buf[FILE_BUF_MAX_SIZE] = {0};//实际中最好使用堆空间,栈空间有限
    				if (len > FILE_BUF_MAX_SIZE) {
    					len = FILE_BUF_MAX_SIZE;
    				}
    				size_t read_size = fread(file_buf, 1, len, stdin);//获取post数据,里面不仅仅是文件数据,还有其它信息:文件名
    				if (read_size < 1) {
    					printf("post-file read file data error.");
    					return -1;
    				}
    				char *fileNamePtr = strstr(file_buf, "filename=");//filename="post_file_test.txt"
    				if (NULL == fileNamePtr) {
    					printf("post-file get file name error.");
    					return -1;
    				}
    
    				//提取文件名
    				char file_name[128] = {0};
    				sscanf(&fileNamePtr[sizeof("filename=")], "%s\"", file_name);				
    				len = strlen(file_name);
    				if (0 >= len) {
    					printf("post-file file name is empty.");
    					return -1;
    				}
    
    				//去掉文件名的右引号
    				if (file_name[len - 1] == '"') {
    					file_name[len - 1] = '\0';
    				}
    
    				len = strlen(file_name);
    				if (0 >= len) {
    					printf("post-file file name is empty.");
    					return -1;
    				}
    
    				//找到文件数据起始 两个回车换行符
    				char *file_start_ptr = strstr(fileNamePtr, "\r\n\r\n");
    				if (NULL == file_start_ptr) {
    					printf("post-file find file start error.file_buf:%s.", file_buf);
    					return -1;
    				}
    				file_start_ptr += 4;
    
    				//找到文件数据结尾处 边界符--boundary--
    				char *file_end_ptr = strstr(file_start_ptr, boundary);
    				if (NULL != file_end_ptr) {
    					file_end_ptr -= 4;//边界符前后还有"--" 文件数据后面还有一个换车换行符2字节
    					file_end_ptr[0] = '\0';//截断
    				}
    
    				len = strlen(file_start_ptr);
    				if (0 >= len) {
    					printf("post-file file empty.");
    					return -1;
    				}
    
    				//保存数据 file_start_ptr
    				char path[256] = {0};//这个必须是CGI有权限操作的路径, 不然会写不进去
    				sprintf(path, "/var/www/upload/%s", file_name);
    				FILE *save_file = fopen(path, "w+");
    				if (NULL == save_file) {
    					printf("post-file save error. data:%s.", file_start_ptr);
    					return -1;
    				}
    				
    				if (len != fwrite(file_start_ptr, 1, len, save_file)) {
    					printf("post-file write error. data:%s.", file_start_ptr);
    					fclose(save_file);
    					return -1;
    				}
    
    				fclose(save_file);
    				printf("save file success. file name:%s. size:%d.", file_name, len);
    				//printf("post-file type:%s. file_name:%s, boundary:%s, len:%lu, data:%s.", content_type, file_name, boundary, read_size, file_buf);
    			}
    		} else {
    			printf("post content_len error:%s.", content_type);
    		}
    
    	} else {
    		printf("request method error:%s.", req_method);
    	}
    
    	return 0;	
    }
    

    测试结果:

     

    四、例子3:原生AJAX GET、POST请求

    判断用户名和密码是否正确:

    测试代码:

    test.html文件

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title>CGI 例子3</title>
    	</head>
    
    	<body>
    		<label>用户名:</label><input type="text" name="userName1"/></br>
    		<label>密码:</label><input type="password" name="password1"/></br>
    		<input type="button" name="get_request" onclick="AjaxGetRequest()" value="Ajax_Get请求">
    		<hr/>
    		<label>用户名:</label><input type="text" name="userName2"/></br>
    		<label>密码:</label><input type="password" name="password2"/></br>
    		<input type="button" name="post_request" onclick="AjaxPostRequest()" value="Ajax_Post请求">
    
    		<script type="text/javascript">
    
    			/* ajax get请求 */
    			function AjaxGetRequest() {
    				var xhr = new XMLHttpRequest();
    				var data = "name=" + document.getElementsByName("userName1")[0].value + "&pwd="+document.getElementsByName("password1")[0].value;
    		        xhr.open('GET', "http://192.168.159.128/cgi-bin/test.cgi?"+data, false);
    		        xhr.onreadystatechange=function(){
    		            // readyState == 4说明请求已完成
    		            if (xhr.readyState==4) {
    		                if (xhr.status==200 || xhr.status==304) {
    		                    console.log(xhr.responseText);//
    		                    if (xhr.responseText.indexOf("success") >=0 ) {
    		                    	alert("Ajax GET 密码用户名正确");
    		                    } else {
    		                    	alert("Ajax GET 密码或用户名错误");
    		                    }
    		                }
    		            }
    		        }
    		        
    		        xhr.send();
    			}
    
    			/* ajax post请求 */
    			function AjaxPostRequest() {
    				var xhr=new XMLHttpRequest();
    		        xhr.open('POST', "http://192.168.159.128/cgi-bin/test.cgi", false);
    		        // 添加http头,发送信息至服务器时内容编码类型
    		        xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    		        xhr.onreadystatechange=function(){
    		            if (xhr.readyState==4){
    		                if (xhr.status==200 || xhr.status==304){
    		                    console.log(xhr.responseText);//
    		                    if (xhr.responseText.indexOf("success") >=0 ) {
    		                    	alert("Ajax POST 密码用户名正确");
    		                    } else {
    		                    	alert("Ajax POST 密码或用户名错误");
    		                    }
    		                }
    		            }
    		        }
    
    		        var data = "name=" + document.getElementsByName("userName2")[0].value + "&pwd="+document.getElementsByName("password2")[0].value;
    		        xhr.send(data);
    			}
    			
    		</script>
    	</body>
    </html>

    cgi.c文件

    /****************************************************************
     * Project:cgi_test
     * File name: cgi.c
     * Create on: 2020.09.14
     * Anthor: Genven_Liang
     * Description: cgi excample
     ****************************************************************/
    
    #include <stdio.h>
    #include <stdlib.h> //getenv
    #include <string.h>
    
    #define BUF_MAX_SIZE	(2*1024)
    #define FILE_BUF_MAX_SIZE	(4*1024)
    
    int main(void)
    {	
    	/* 说明返回内容类型为html文本 */
    	printf("Content-Type:text/html\n\n");
    
    	/* 请求方式 */
    	char *req_method = getenv("REQUEST_METHOD");
    
    	if (0 == strcmp("GET", req_method)) { /* 处理GET请求 */
    		char *get_arg = getenv("QUERY_STRING");//获取Get数据
    		if (NULL == get_arg) {
    			get_arg = "";
    		}
    
    		//获取用户名和密码
    		char *token_name = NULL;
    		char *token_pwd = NULL;
    		token_name = strtok_r(get_arg, "&", &token_pwd);
    		char *name = NULL;
    		strtok_r(token_name, "=", &name);//用户名
    		char *pwd = NULL;
    		strtok_r(token_pwd, "=", &pwd);//密码
    
    		if (0 == strcmp("liang", name) && 0 == strcmp("123", pwd)) {
    			printf("get login success.");
    		} else {
    			printf("get name or password error.name:%s, pwd:%s.", name, pwd);
    		}
    	} else if (0 == strcmp("POST", req_method)) { /* 处理POST请求 */
    		char *content_len = getenv("CONTENT_LENGTH");//获取数据长度
    		char *content_type = getenv("CONTENT_TYPE");//获取数据类型 application/x-www-form-urlencoded、multipart/form-data、text/plain 其中:multipart/form-data是文件传输
    
    		int len = 0;
    		if (NULL != content_len) {
    			len = atoi(content_len);
    		}		
    
    		if (len > 0) { //获取post数据	
    			if (NULL != content_type && NULL == strstr(content_type, "multipart/form-data")) {//普通文本参数
    				char dat_buf[BUF_MAX_SIZE] = {0};
    				if (len > BUF_MAX_SIZE) {
    					len = BUF_MAX_SIZE;
    				}
    				len = fread(dat_buf, 1, len, stdin);
    				//printf("post type:%s. len:%d, data:%s.", content_type, len, dat_buf);
    				//使用字符串分割函数获取各个参数:strtok_r
    				char *token_name = NULL;
    				char *token_pwd = NULL;
    				token_name = strtok_r(dat_buf, "&", &token_pwd);
    				char *name = NULL;
    				strtok_r(token_name, "=", &name);//用户名
    				char *pwd = NULL;
    				strtok_r(token_pwd, "=", &pwd);//密码
    
    				if (0 == strcmp("zhangsan", name) && 0 == strcmp("456", pwd)) {
    					printf("post login success.");
    				} else {
    					printf("post name or password error.name:%s, pwd:%s.", name, pwd);
    				}
    			} 
    		} else {
    			printf("post content_len error:%s.", content_type);
    		}
    
    	} else {
    		printf("request method error:%s.", req_method);
    	}
    
    	return 0;	
    }
    

    测试结果:

    五、例子4:JQuery AJAX GET、POST请求

    需要下载jqueryxxx.js 官网地址:https://jquery.com/download/

    下载之后将js文件放在test.html的统计目录即可, 

    测试代码

    test.html文件

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title>CGI 例子4</title>
    	</head>
    
    	<body>
    		<label>用户名:</label><input type="text" name="userName1"/></br>
    		<label>密码:</label><input type="password" name="password1"/></br>
    		<input type="button" name="get_request" onclick="AjaxGetRequest()" value="Ajax_Get请求">
    		<hr/>
    		<label>用户名:</label><input type="text" name="userName2"/></br>
    		<label>密码:</label><input type="password" name="password2"/></br>
    		<input type="button" name="post_request" onclick="AjaxPostRequest()" value="Ajax_Post请求">
    
    		<script type="text/javascript" src="./jquery-3.5.1.min.js"></script> <!-- 引用JQ库 -->
    		<script type="text/javascript">
    
    			/*jquery ajax get请求 */
    			function AjaxGetRequest() {
    				var arg = "name=" + document.getElementsByName("userName1")[0].value + "&pwd="+document.getElementsByName("password1")[0].value;
    				var req_url = "http://192.168.159.128/cgi-bin/test.cgi?" + arg;
    		        $.ajax({
    				    url: req_url,
    				    type:"GET",
    				    success: function(result){
    				         console.log(result);//
    		                    if (result.indexOf("success") >=0 ) {
    		                    	alert("JQ Ajax GET 密码用户名正确");
    		                    } else {
    		                    	alert("JQ Ajax GET 密码或用户名错误");
    		                    }
    				    },
    				    error: function(){
    				          alert("JQ Ajax GET 请求失败");
    				    }
    				 });
    			}
    
    			/* jquery ajax post请求 */
    			function AjaxPostRequest() {
    				
    		        var dat = "name=" + document.getElementsByName("userName2")[0].value + "&pwd="+document.getElementsByName("password2")[0].value;
    
    		        $.ajax({
    				    url: "http://192.168.159.128/cgi-bin/test.cgi",
    				    type:"POST",
    				    data: dat,
    				    success: function(result){
    				         console.log(result);//
    		                    if (result.indexOf("success") >=0 ) {
    		                    	alert("JQ Ajax POST 密码用户名正确");
    		                    } else {
    		                    	alert("JQ Ajax POST 密码或用户名错误");
    		                    }
    				    },
    				    error: function(){
    				          alert("JQ Ajax POST 请求失败");
    				    }
    				 });
    			}
    			
    		</script>
    	</body>
    </html>

    cgi.c文件同例子3

    测试结果:

    JQuery Ajax说明:

    url:是请求url地址:

    type:“GET” 或 "POST"

    async: 指示是否异步请求,false或true

    dataType:可以是json,期望服务器返回的数据类型,不一致会进入error处理流程

    success:是服务器响应后执行的处理

    error:一般是服务器没有响应,超时处理。

    result:是服务器返回的数据内容

    $.ajax({
        url: ,
        type: '',
        async: '',
        dataType: '',
        data: {
              
        },
        success: function(result){
             
        },
        error: function(result){
              
        }
     })

    六、总结

    6.1 请求一般由浏览器发起,服务器被动响应并回传数据;也就是CGI是被调用的,不要试图使用全局静态变量记住某种状态,因为这是无效的。要想保持状态,客户端使用kookie、缓存、本地存储等、服务器端使用session、配置文件、环境变量等。

    6.2 前端请求(html)--》服务器(Apache)--》后台处理(CGI)--》再经过服务器回传给前端

    6.3 CGI返回的数据类型可以是一个完整的html数据、也可以仅仅是数据,最好是仅仅返回数据,让前端自行展示。

    6.4 错误页可以直接返回一个简单的页面。

    6.5 前端要等待CGI返回并处理结果的需要使用AJAX。

    6.6 也可以在CGI程序设置浏览器端的cookie,但是需要在返回Content-Type之前,并且仅能设置一个cookie (测试中发现该情况,不保证正确性,有待验证)

    6.7 CGI通过标准输出将数据发给前端,通过getenv("QUERY_STRING")获取get请求数据,通过标准输入获取post数据。

    6.8 例子中CGI没有url解码操作,实际上需要对数据进行解码操作,url参数,post参数可能是经过url编码的,如空格,post会变为'+', get变为%20,问号get变为%3F。get方式其实就是%然后加上字符的ASCII码的十六进制数。还有中文编码。

    url解码示例:

    
    void UrlDecode(char *src, int len, char *dest)
    {
    	int i;
    	int tmp;   
    	for (i = 0; i < len; i++, dest++) {
    		if (src[i] == '+') {
    			*dest = ' ';
    		} else if(src[i] == '%') {			 
    			if (sscanf(&src[i+1], "%2x", &tmp)!=1) {
    				tmp = '?';
    			}
    			*dest = tmp;
    			i += 2;
    		} else {
    			*dest = src[i];
    		}
    	}
    }

    6.9 post请求的enctype

    enctype规定在发送表单数据之前如何对其进行编码

    enctype可以取以下三种值:

    application/x-www-form-urlencoded(默认)

    multipart/form-data (文件上传使用)

    text/plain
    6.9 设置默认编码为UTF-8,这样子html的中文不会乱码

    执行:sudo vi  /etc/apache2/conf-available/charset.conf, 将#AddDefaultCharset UTF-8 前面的'#'号去掉

    重启apache使配置生效:sudo /etc/init.d/apache2 restart

    展开全文
  • WML学习之七 CGI编程

    2020-10-31 00:01:53
    WML学习之七 CGI编程
  • C语言CGI编程

    热门讨论 2011-12-25 09:07:39
    C语言的CGI编程,详细介绍了如何用C语言进行CGI编程,适合入门者学习,很好的学习资料。
  • CGI编程使用Perl

    2012-08-22 17:32:20
    CGI编程使用Perl
  • Linux_CGI编程

    2013-11-13 16:33:32
    Linux_CGI编程
  • Cgi 编程傻瓜书.rar

    2019-07-09 15:16:57
    Cgi 编程傻瓜书
  • CGI 开发使用手册 CGI编程

    热门讨论 2009-07-12 13:10:05
    CGI 开发使用手册,CGI编程, CGI基础教程(a01格式文件)
  • CGI编程指南读书笔记

    2011-07-29 00:33:21
    CGI编程指南读书笔记CGI编程指南读书笔记CGI编程指南读书笔记
  • Python CGI编程

    2021-03-19 11:18:17
    Python CGI编程 1.程序开始执行 2.程序初始化 3.程序处理 4.程序输出 5.程序执行终止
  • ccgi编程

    2019-06-28 08:08:30
    目录 ccgi编程 ccgi编程 关于http通信的原理,在之前的http通讯和tinyhttpd —— C 语言实现最简单的 HTTP 服务器已经讲过 //cgitest.c #include <stdio.h> #include <stdlib....
  • CGI编程PPT

    2008-06-03 09:20:56
    CGI编程PPT,简明扼要
  • Python高级编程——CGI编程 什么是 CGI CGI 通用网关接口(Common Gateway Interface,CGI)是Web 服务器运行时外部程序的规范,按CGI 编写的程序可以扩展服务器功能。CGI 应用程序能与浏览器进行交互,还可通过...
  • 使用Ruby您不仅可以编写自己的SMTP服务器,FTP程序,或Ruby Web服务器,而且还可以使用Ruby进行CGI编程。 接下来,让我们花点时间来学校Ruby的CGI编辑。 编写 CGI 脚本 最脚本的 Ruby CGI 代码如下所示: #!/usr/bin...
  • CGI编程错误总结

    2019-04-21 17:18:58
    CGI编程错误总结

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 45,419
精华内容 18,167
关键字:

cgi编程