程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> CGI(通用網關接口),cgi通用網關接口

CGI(通用網關接口),cgi通用網關接口

編輯:關於C語言

CGI(通用網關接口),cgi通用網關接口


公共網關接口

CGI(Common Gateway Interface) 是WWW技術中最重要的技術之一,有著不可替代的重要地位。CGI是外部應用程序(CGI程序)與Web服務器之間的接口標准,是在CGI程序和Web服務器之間傳遞信息的規程。CGI規范允許Web服務器執行外部程序,並將它們的輸出發送給Web浏覽器,CGI將Web的一組簡單的靜態超媒體文檔變成一個完整的新的交互式媒體。

Common Gateway Interface,簡稱CGI。在物理上是一段程序,運行在服務器上,提供同客戶端HTML頁面的接口。這樣說大概還不好理解。那麼我們看一個實際例子:現在的個人主頁上大部分都有一個留言本。留言本的工作是這樣的:先由用戶在客戶端輸入一些信息,如名字之類的東西。接著用戶按一下“留言”(到目前為止工作都在客戶端),浏覽器把這些信息傳送到服務器的CGI目錄下特定的cgi程序中,於是cgi程序在服務器上按照預定的方法進行處理。在本例中就是把用戶提交的信息存入指定的文件中。然後cgi程序給客戶端發送一個信息,表示請求的任務已經結束。此時用戶在浏覽器裡將看到“留言結束”的字樣。整個過程結束。

功能

絕大多數的CGI程序被用來解釋處理來自表單的輸入信息,並在服務器產生相應的處理,或將相應的信息反饋給浏覽器。CGI程序使網頁具有交互功能。

處理步驟

⑴通過Internet把用戶請求送到web服務器。

⑵web服務器接收用戶請求並交給CGI程序處理。

⑶CGI程序把處理結果傳送給web服務器。

⑷web服務器把結果送回到用戶。

服務器配置

CGI程序不是放在服務器上就能順利運行,如果要想使其在服務器上順利的運行並准確的處理用戶的請求,則須對所使用的服務器進行必要的設置。

配置:根據所使用的服務器類型以及它的設置把CGI程序放在某一特定的目錄中或使其帶有特定的擴展名。

⑴CREN格式服務器的配置:

編輯CREN格式服務器的配置文件(通常為/etc/httpd.conf)在文件中加入:Exec cgi-bin/*/home/www/cgi-bin/*.exec。命令中出現的第一個參數cgi-bin/*指出了在URL中出現的目錄名字,並表示它出現在系統主機後的第一個目錄中,如:http://edgar.stern.nyn.***/cgi-bin/。命令中的第二個參數表示CGI程序目錄放在系統中的真實路徑。

CGI目錄除了可以跟網絡文件放在同一目錄中,也可以放在系統的其它目錄中,但必須保證在你的系統中也具有同樣的目錄。在對服務器完成設置後,須重新啟動服務器(除非HTTP服務器是用inetd啟動的)。

⑵NCSA格式服務器的配置

在NCSA格式服務器上有兩種方法進行設置:

①在srm.conf文件(通常在conf目錄下)中加入:Script Alias/cgi-bin/cgi-bin/。Script Alias命令指出某一目錄下的文件是可執行程序,且這個命令是用來執行這些程序的;此命令的兩個參數與CERN格式服務器中的Exec命令的參數的含意一樣。

②在srm.conf文件加入:Add type application/x-httpd-cgi.cgi。此命令表示在服務器上增加了一種新的文件類型,其後第一個參數為CGI程序的MIME類型,第二個參數是文件的擴展名,表示以這一擴展名為擴展名的文件是CGI程序。

在用上述方法之一設置服務器後,都得重新啟動服務器(除非HTTP服務器是用inetd啟動的)。

編寫語言

CGI可以用任何一種語言編寫,只要這種語言具有標准輸入、輸出和環境變量。對初學者來說,最好選用易於歸檔和能有效表示大量數據結構的語言,例如UNIX環境中:

· Perl (Practical Extraction and Report Language)

· Bourne Shell或者Tcl (Tool Command Language)

· PHP(Hypertext Preprocessor))

由於C語言有較強的平台無關性,所以也是編寫CGI程序的首選。

Windows環境中:

· C和C++

由於Internet上大部分服務器使用的是UNIX操作系統,且幾乎任一UNIX操作系統中都有Bourne Shell,因而後面講述的例子中大部分是用Bourne Shell編寫的。

最終Perl由於其跨操作系統、易於修改的特性成為了CGI的主流編寫語言,以至於一般的“cgi程序”就是Perl程序。

環境變量列表

SERVER_NAME:運行CGI序為機器名或IP地址。

SERVER_INTERFACE:WWW服務器的類型,如:CERN型或NCSA型。

SERVER_PROTOCOL:通信協議,應當是HTTP/1.0。

SERVER_PORT:TCP端口,一般說來web端口是80。

HTTP_ACCEPT:HTTP定義的浏覽器能夠接受的數據類型。

HTTP_REFERER:發送表單的文件URL。(並非所有的浏覽器都傳送這一變量)

HTTP_USER-AGENT:發送表單的浏覽器的有關信息。

GETWAY_INTERFACE:CGI程序的版本,在UNIX下為 CGI/1.1。

PATH_TRANSLATED:PATH_INFO中包含的實際路徑名。

PATH_INFO:浏覽器用GET方式發送數據時的附加路徑。

SCRIPT_NAME:CGI程序的路徑名。

QUERY_STRING:表單輸入的數據,URL中問號後的內容。

REMOTE_HOST:發送程序的主機名,不能確定該值。

REMOTE_ADDR:發送程序的機器的IP地址。

REMOTE_USER:發送程序的人名。

CONTENT_TYPE:POST發送,一般為application/xwww-form-urlencoded。

CONTENT_LENGTH:POST方法輸入的數據的字節數。

 

搭建C語言CGI和Apache服務器的開發環境

 

步驟如下:

首先,需要用到的這些工具和代碼:

  • C語言編譯器;
  • Apache服務器,我用的是USBWebSever中包含的Apache服務器(下載地址) ,這是個AMP服務器套裝,不用安裝即可使用,而本地安裝的Apche服務器也可以使用;

接著,編譯C語言的cgi程序。

 

源碼如下:C CGI Example

然後,配置和啟動Apache服務器。

對USBWebSever,對settings目錄下的httpd.conf如下內容進行修改,如下:

ScriptAlias /cgi-bin/ "{rootdir}/cgi-bin/"

<Directory "{rootdir}/cgi-bin">
#   AllowOverride All
#   Options None
    AllowOverride None
    Options ExecCGI
    Order allow,deny
    Allow from all
</Directory>
AddHandler cgi-script .exe .pl .cgi

修改好以後,雙擊USBWebSever.exe就可以啟動Apache服務器了。

最後把剛才生成的cgi程序(.exe文件),復制放到上文中提到的/cgi-bin/目錄下,文件名最好改成index.cgi這樣的形式。對於USBWebSever,cgi-bin目錄應該是root目錄下的cgi-bin目錄(如果沒有要新建一個),不是和USBWebSever在同一目錄下的cgi-bin目錄。目錄結構如下:

打開浏覽器輸入http://127.0.0.1:8080/cgi-bin/index.cgi,即可訪問cgi程序。 

 

C CGI Example

index.html

<head>
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <body>
    <form action="/cgi-bin/mult.cgi">
        <p>CGI表單處理:Get方法演示:輸入乘數和被乘數,計算結果</p>
            M : <input name="m" size="5">
            N : <input name="n" size="5">
        <br><input type="submit" value="確定"></input></br>

    </form>

    <form action="/cgi-bin/collect.cgi" method="POST" >
        <p>CGI表單處理:Post方法演示:請輸入您的留言(最多80個字符):
        <br><input name="data" size="60" maxlength="80"></br>
        <input type="SUBMIT" value="確定">
    </form> 
    
    <form action="/cgi-bin/viewdata.cgi">
        <p><input type="SUBMIT" value="察看留言">
    </form>
  </body>
</head>

mult.cgi

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    char *data;
    long m, n;
    printf("%s", "Content-Type:text/html\n\n");
    printf("<html>");
    printf("<head><title>乘法結果</title>");
    printf("<h3>乘法結果</h3> ");
    printf("</head><body>");
    data = getenv("QUERY_STRING");
    if (data == NULL)
        printf("<p>錯誤!數據沒有被輸入或者數據傳輸有問題");
    else if (sscanf(data, "m=%ld&n=%ld", &m, &n) != 2)
        printf("<p>錯誤!輸入數據非法。表單中輸入的必須是數字。");
    else
        printf("<p>%ld * %ld = %ld。", m, n, m * n);
    printf("</body></html>");
    return 0;
}

運行示例:

 

collect.cgi

#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 80
#define EXTRA 5
 4個字節留給字段的名字"data", 1個字節留給"="
#define MAXINPUT MAXLEN+EXTRA+2
 1個字節留給換行符,還有一個留給後面的NULL
#define DATAFILE "../data/data.txt"
 要被添加數據的文件
void decode(char *src, char *last, char *dest)
{
    for (; src != last; src++, dest++)
        if (*src == '+')
            *dest = ' ';
        else if (*src == '%')
        {
            int code;
            if (sscanf(src + 1, "%2x", &code) != 1)
                code = '?';
            *dest = code;
            src += 2;
        }
        else
            *dest = *src;
    *dest = '\n';
    *++dest = '\0';
}
int main(void)
{
    char *lenstr;
    char input[MAXINPUT], data[MAXINPUT];
    long len;
    printf("%s", "Content-Type:text/html\n\n");
    printf("<html><head><title>Response</title>");
    printf("</head><body>");
    lenstr = getenv("CONTENT_LENGTH");
    if (lenstr == NULL || sscanf(lenstr, "%ld", &len) != 1 || len> MAXLEN)
        printf("<p>表單提交錯誤");
    else
    {
        FILE *f;
        fgets(input, len + 1, stdin);
        decode(input + EXTRA, input + len, data);
        f = fopen(DATAFILE, "a");
        if (f == NULL)
            printf("<p>對不起,意外錯誤導致系統無法保存你的留言");
        else{
            fputs(data, f);
            printf("<p>非常感謝,您的留言已被系統接收");
        }

        fclose(f);

    }

    printf("</body></html>");
    return 0;
}

運行示例:

 

viewdata.cgi

#include <stdio.h>
#include <stdlib.h>
#define DATAFILE "../data/data.txt"
int main(void)
{
    FILE *f = fopen(DATAFILE, "r");
    int ch;
    if (f == NULL)
    {
        printf("%s", "Content-Type:text/html\n\n");
        printf("<P><EM>意外錯誤,無法打開文件</EM>");
    }
    else
    {
        printf("%s", "Content-Type:text/plain\n\n");
        while ((ch = getc(f)) != EOF)
            putchar(ch);
        fclose(f);
    }

    return 0;
}

運行示例:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved