<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    CGI編程完全手冊

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    一.基本原理

    CGI:通用網關接口(Common Gateway Interface)是一個Web服務器主機提供信息服務的標準接口。通過CGI接口,Web服務器就能夠獲取客戶端提交的信息,轉交給服務器端的CGI程序進行處理,最后返回結果給客戶端。

    組成CGI通信系統的是兩部分:一部分是html頁面,就是在用戶端瀏覽器上顯示的頁面。另一部分則是運行在服務器上的Cgi程序。

    它們之間的通訊方式如下圖:

     RFID設備管理軟件

           服務器和客戶端之間的通信,是客戶端的瀏覽器和服務器端的http服務器之間的HTTP通信,我們只需要知道瀏覽器請求執行服務器上哪個CGI程序就可以了,其他不必深究細節,因為這些過程不需要程序員去操作。

           服務器和CGI程序之間的通訊才是我們關注的。一般情況下,服務器和CGI程序之間是通過標準輸入輸出來進行數據傳遞的,而這個過程需要環境變量的協作方可實現。

     

    1. 1.    服務器將URL指向一個應用程序
    2. 2.    服務器為應用程序執行做準備
    3. 3.    應用程序執行,讀取標準輸入和有關環境變量
    4. 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:它的值一般包括兩種:POST和GET,但我們寫CGI程序時,最后還要考慮其他的情況。

    1.POST方法

    如果采用POST方法,那么客戶端來的用戶數據將存放在CGI進程的標準輸入中,同時將用戶數據的長度賦予環境變量中的CONTENT_LENGTH。客戶端用POST方式發送數據有一個相應的MIME類型(通用Internet郵件擴充服務:Multi-purpose Internet Mail Extensions)。目前,MIME類型一般是:application/x-wwww-form-urlencoded,該類型表示數據來自HTML表單。該類型記錄在環境變量CONTENT_TYPE中,CGI程序應該檢查該變量的值。

    2.GET方法

    在該方法下,CGI程序無法直接從服務器的標準輸入中獲取數據,因為服務器把它從標

    準輸入接收到得數據編碼到環境變量QUERY_STRING(或PATH_INFO)。

    GET與POST的區別:采用GET方法提交HTML表單數據的時候,客戶機將把這些數

    據附加到由ACTION標記命名的URL的末尾,用一個包括把經過URL編碼后的信息與CGI程序的名字分開:http://www.mycorp.com/hello.html?name=hgq$id=1,QUERY_STRING的值為name=hgq&id=1

    有些程序員不愿意采用GET方法,因為在他們看來,把動態信息附加在URL的末尾有

    違URL的出發點:URL作為一種標準用語,一般是用作網絡資源的唯一定位標示。

     

    環境變量是一個保存用戶信息的內存區。當客戶端的用戶通過瀏覽器發出CGI請求時,服務器就尋找本地的相應CGI程序并執行它。在執行CGI程序的同時,服務器把該用戶的信息保存到環境變量里。接下來,CGI程序的執行流程是這樣的:查詢與該CGI程序進程相應的環境變量:第一步是request_method,如果是POST,就從環境變量的len,然后到該進程相應的標準輸入取出len長的數據。如果是GET,則用戶數據就在環境變量的QUERY_STRING里。

    3.POST與GET的區別

           以 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_METHOD,REMOTE_ADDR等)添加進來,也就是說“getenv(“REQUEST_METHOD”)”將返回NULL!

    2.URL編碼

    不管是POST還是GET方式,客戶端瀏覽器發送給服務器的數據都不是原始的用戶數據,而是經過URL編碼的。此時,CGI的環境變量Content_type將被設置,如Content_type = application/x-www-form-urlencode就表示服務器收到的是經過URL編碼的包含有HTML表單變量數據。

    編碼的基本規則是:

    變量之間用“&”分開;

    變量與其對應值用“=”連接;

    空格用“+”代替;

    保留的控制字符則用“%”連接對應的16禁止ASCII碼代替;

    某些具有特殊意義的字符也用“%”接對應的16進制ASCII碼代替;

    空格是非法字符;

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

    例如,假設3個HTML表單變量filename、e-mail和comments,它們的值對應分別為hello、mike@hotmail.com和I’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);

     

    3.CGI數據輸出

    CGI程序如何將信息處理結果返回給客戶端?這實際上是CGI格式化輸出。

    在CGI程序中的標準輸出stdout是經過重定義了的,它并沒有在服務器上產生任何的輸出內容,而是被重定向到客戶瀏覽器,這與它是由C,還是Perl或Python實現無關。

    所以,我們可以用打印來實現客戶端新的HTML頁面的生成。比如,C的printf是向該進程的標準輸出發送數據,Perl和Python用print向該進程的標準輸出發送數據。

    (1)    CGI標題

    CGI的格式輸出內容必須組織成標題/內容的形式。CGI標準規定了CGI程序可以使用

    的三個HTTP標題。標題必須占據第一行輸出!而且必須隨后帶有一個空行。

    標題

    描述

    Content_type   (內容類型)

    設定隨后輸出數據所用的MIME類型

    Location    (地址)

    設定輸出為另外一個文檔(URL)

    Status      (狀態)

    指定HTTP狀態碼

     

    MIME:

    向標準輸出發送網頁內容時要遵守MIME格式規則:

    任意輸出前面必須有一個用于定義MIME類型的輸出內容(Content-type)行,而且隨后還必須跟一個空行。如果遺漏了這一條,服務將會返回一個錯誤信息。(同樣使用于其他標題)

    例如Perl和Python:

    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表示一下幾種典型文件格式的一種:

    Text、Audio、Video、Image、Application、Mutipart、Message

    Subtype則用來描述具體所用的數據格式。

    Application/msword

    微軟的Word文件

    Application/octet-stream

    一種通用的二進制文件格式

    Application/zip

    Zip壓縮文件

    Application/pdf

    Pdf文件

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

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

     

    Location:

    使用Location標題,一個CGI可以使當前用戶轉而訪問同一服務器上的另外一個程序,甚至可以訪問另外一個URL,但服務器對他們的處理方式不一樣。

    使用Location的格式為:Location:Filename/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程序,服務器為他們創建了2個CGI程序進程,設為進程A和進程B。假如進程A首先打開了某個文件,然后由于某種原因被掛起(一般是由于操作系統的進程調度);而就在進程A被掛起的這段時間內,進程B完成了對文件的整個操作流程:打開,寫入,關閉;進程A再繼續往下執行,但進程A所操作的文件依舊是原來文件的就版本,此時進程A的操作結果將覆蓋進程B的操作結果。

    為了防止這種情況發生,需要用到文件鎖或者信號量。

    鑰匙文件?

     

    假如有多個不同的HTML可以調用同一個CGI程序,那么CGI程序如何區分它們呢?一個是通過隱含的INPUT標簽。不過覺得這個比較麻煩,因為CGI必須經過一系列解碼后才能找到這個隱含INPUT的變量和其值。

    五.設置HTTP服務器以兼容CGI

           用Perl編寫的CGI程序后綴為:.pl;Python編寫的CGI程序后綴為:.py;而C編寫的CGI程序后綴為:.cgi,如果在win下編譯出來的是.exe,最好將它重命名為.cgi。這些都是為了HTTP服務能夠識別并調用它們。

           當使用appche httpd服務器時,請編輯它的配置文件httpd.conf如下:

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

    六.關于CGI的C語言庫——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,在執行的速度上,JavaScript比CGI有著先天的優勢。只有那些在客戶端解決不了的問題,比如和某個遠程數據庫交互,這時就應該使用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”-- >,服務器將向瀏覽器輸出時間。

     RFID設備管理軟件

    RFID設備管理軟件

     

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全