CGI介面原理及實現

來源:互聯網
上載者:User
CGI介面原理及實現

  CGI介面原理及實現(2012-12-7 Over)

  

  1.CGI定義:

  CGI(CommonGateway Interface)是HTTP伺服器與你的或其它機器上的程式進行“交談”的一種工具,其程式須運行在網路伺服器上。

  2.CGI功能:

  絕大多數的CGI程式被用來解釋處理來自表單的輸入資訊,並在伺服器產生相應的處理,或將相應的資訊反饋給瀏覽器。CGI程式使網頁具有互動功能。

  3.CGI運行環境:

  CGI程式在UNIX作業系統上CERN或NCSA格式的伺服器上運行。 在其它作業系統(如:windows NT及windows95等)的伺服器上 也廣泛地使用CGI程式,同時它也適用於各種類型機器。

  4.CGI處理步驟:

  ⑴通過Internet把使用者請求送到伺服器。

  ⑵伺服器接收使用者請求並交給CGI程式處理。

  ⑶CGI程式把處理結果傳送給伺服器。

  ⑷伺服器把結果送回到使用者。

  5.CGI伺服器配置:

  在許多伺服器cgi-bin是僅能夠放置CGI指令碼的目錄。

  

  在Windows平台上將C或C++寫好的程式的Debug或Release版本的.exe程式拷貝到cgi-bin的目錄下(如上圖所示),將.exe改為.cgi也可同樣運行,如下2個圖。

  

  

         cgi-bin目錄是存放CGI指令碼的地方。這些指令碼使WWW伺服器和瀏覽器能運行外部程式,而無需啟動另一個程式。它是運行在Web伺服器上的一個程式,並由來自於瀏覽者的輸入觸發。

  CGI程式不是放在伺服器上就能順利運行,如果要想使其在伺服器上順利的運行並準確的處理使用者的請求,則須對所使用的伺服器進行必要的設定。

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

  Apache網路伺服器配置在/var/www/cgi-bin裡(如下圖所示筆者電腦的目錄位置)。C++編譯的可執行檔可以轉換成副檔名為.cgi的檔案。

  更改初始配置的的方法:

  <Directory”/var/www/cgi-bin”>

  AllowOverride None

  Options ExecCGI

  Order allow,deny

  Allow from all

  </Directory>

  <Directory”/var/www/cgi-bin”>

  Options All

  </Directory>

  

  6.CGI介面標準包括標準輸入、環境變數、標準輸出三部分。

 

  介紹

  1.標準輸入

  CGI程式像其他可執行程式一樣,可通過標準輸入(stdin)從Web伺服器得到輸入資訊,如Form中的資料,這就是所謂的向CGI程式傳遞資料的POST方法。這意味著在作業系統命令列狀態可執行CGI程式,對CGI程式進行調試。POST方法是常用的方法。

  2.環境變數

  作業系統提供了許多環境變數,它們定義了程式的執行環境,應用程式可以存取它們。Web伺服器和CGI介面又另外設定了自己的一些環境變數,用來向CGI程式傳遞一些重要的參數。CGI的GET方法還通過環境變數QUERY-STRING向CGI程式傳遞Form中的資料。

  3.標準輸出

  CGI程式通過標準輸出(stdout)將輸出資訊傳送給Web伺服器。傳送給Web伺服器的資訊可以用各種格式,通常是以純文字或者HTML文本的形式,這樣我們就可以在命令列狀態調試CGI程式,並且得到它們的輸出。

  7.環境變數

  環境變數是文本串(名字/值對),可以被OSShell或其他程式設定 ,也可以被其他程式訪問。它們是Web伺服器傳遞資料給CGI程式的簡單手段,之所以稱為環境變數是因為它們是全域變數,任何程式都可以存取它們。

  下面是CGI程式設計中常常要用到的一些環境變數。

  環境變數         

  意義

  SERVER_NAME

  CGI指令碼運行時的主機名稱和IP地址.

  SERVER_SOFTWARE

  你的伺服器的類型如: CERN/3.0 或 NCSA/1.3.

  GATEWAY_INTERFACE

  啟動並執行CGI版本. 對於UNIX伺服器, 這是CGI/1.1.

  SERVER_PROTOCOL

  伺服器啟動並執行HTTP協議. 這裡當是HTTP/1.0.

  SERVER_PORT

  伺服器啟動並執行TCP口,通常Web伺服器是80.

  REQUEST_METHOD

  POST 或 GET, 取決於你的表單是怎樣遞交的.

  HTTP_ACCEPT 

  瀏覽器能直接接收的Content-types, 可以有HTTP Accept header定義.

  HTTP_USER_AGENT

  遞交表單的瀏覽器的名稱、版本 和其他平台性的附加資訊。

  HTTP_REFERER

  遞交表單的文本的 URL,不是所有的瀏覽器都發出這個資訊,不要依賴它

  PATH_INFO

  附加的路徑資訊, 由瀏覽器通過GET方法發出.

  PATH_TRANSLATED

  在PATH_INFO中系統規定的路徑資訊.

  SCRIPT_NAME

  指向這個CGI指令碼的路徑, 是在URL中顯示的(如, /cgi-bin/thescript).

  QUERY_STRING

  指令碼參數或者表單輸入項(如果是用GET遞交). QUERY_STRING 包含URL中問號後面的參數.

  REMOTE_HOST

  遞交指令碼的主機名稱,這個值不能被設定.

  REMOTE_ADDR

  遞交指令碼的主機IP地址.

  REMOTE_USER

  遞交指令碼的使用者名稱. 如果伺服器的authentication被啟用,這個值可以設定。

  REMOTE_IDENT

  如果Web伺服器是在ident (一種確認使用者串連你的協議)運行, 遞交表單的系統也在運行ident, 這個變數就含有ident傳回值.

  CONTENT_TYPE

  如果表單是用POST遞交, 這個值將是 application/x-www-form-urlencoded. 在上傳檔案的表單中, content-type 是個 multipart/form-data.

  CONTENT_LENGTH

  對於用POST遞交的表單, 標準輸入口的位元組數.

  REQUEST-METHOD:指的是當Web伺服器傳遞資料給CGI程式時所採用的方法,分為GET和POST兩種方法。

  :GET方法僅通過環境變數(如QUERY-STRING)傳遞資料給CGI程式,而POST方法通過環境變數和標準輸入傳遞資料給CGI程式,因此POST方法可較方便地傳遞較多的資料給CGI程式。

   

  問題

  GET方法

  通過在URL中嵌入的形式傳遞參數。對CGI程式而言,在GET method中傳遞的參數要通過化境變數“QUERY-STRING”來接收。

  1)  參數的內容作為URL資訊,使用者可以看到;

  2)  有大小的限制。

  POST方法

  CGI程式從標準輸入接收參數。與GET方法不同的是,參數的內容從URL資訊中不能獲得,對於大小也沒有限制。

  與GET方法問題1),2)完全相反。

  CONTENT-LENGTH:傳遞給CGI程式的資料字元數(位元組數)。

  在C語言程式中,要訪向環境變數,可使用getenv()庫函數。例如:
       if (getenv (″CONTENT-LENGTH″))n=atoi(getenv(″CONTENT-LENGTH″));
  請注意程式中最好調用兩次getenv():第一次檢查是否存在該環境變數,第二次再使用該環境變數。這是因為函數getenv()在給定的環境變數名不存在時,返回一個NULL(空)指標,如果你不首先檢查而直接引用它,當該環境變數不存在時會引起CGI程式崩潰。

  8. CGI的工作原理

  CGI是一個WEB伺服器提供資訊服務的標準介面,通過這樣一個介面,WEB伺服器能夠執行程式,並將程式輸出的資訊返回給瀏覽器。因為在WEB網上的資料都是靜態,通過CGI程式能夠動態處理瀏覽者的請求,如儲存使用者輸入的資訊,根據使用者資訊返回相關的資料等等。當用戶端發送一個CGI請求給WEB伺服器後,WEB伺服器將根據CGI程式的類型決定資料向CGI程式的傳送方式,一般來講是通過標準輸入/輸出流和環境變數來與CGI程式間傳遞資料。

  

  CGI輸入輸出原理

  CGI的輸入/輸出方法:CGI程式通過標準輸入(STDIN)和標準輸出(STDOUT)來進行輸入輸出,STDIN和STDOUT是兩個預先定義好的檔案指標。你可以利用檔案讀寫函數來對其進行操縱。

  此外CGI程式還通過環境變數來得到輸入,只不過環境變數中提供的是一些常用的資訊,並且通常不包括使用者在WEB頁面中輸入的資訊(除使用下面講的GET方法時,通過檢查環境變數QUERY_STRING來得到輸入資料),而STDIN通常用來傳遞使用者輸入的資訊。

  在輸入時所使用的POST/GET方法:在WEB頁面向CGI發送資料時通常採用兩種方法:GET/POST,GET方法將資料附加在URL後發送,如:/cgi/a_cgi_test.exe your_data,CGI程式通過檢查環境變數QUERY_STRING來得到輸入資料。

          樣本一、下圖即是GET方法!

  

  上圖的對應程式為:

  //2012-12-5 GET c程式樣本..

  void main(void) {// 本程式將使用者輸入的資料列印出來 fprintf(stdout,”content-type:text/plain\n\n”); // 輸出一個CGI標題,這行代碼的意義後面會講解 char *pszMethod; pszMethod =getenv(“REQUEST_METHOD”); if(strcmp(pszMethod,”GET”) == 0) { //GET method //讀取環境變數來擷取資料 printf(“This is GETMETHOD!\n”); printf(“SERVER_NAME:%s\n”,getenv(“SERVER_NAME”)); printf(“REMOTE_ADDR:%s\n”,getenv(“REMOTE_ADDR”)); fprintf(stdout,”input data is:%s\n”,getenv(“QUERY_STRING”)); } else { // POST method //讀取STDIN來擷取資料 intiLength=atoi(getenv(“CONTENT_LENGTH”)); printf(“This is POSTMETHOD!\n”); fprintf(stdout,”input data is:\n”); for(int i=0;i<iLength;i++) { char cGet=fgetc(stdin); fputc(cGet,stdout); } } }

           樣本二、下圖即是POST程式樣本:

  

  

  

  void unencode(char *src, char *last, char *dest) { // str = hello+there%21 此處跳過data=… // last = ; 已到末尾. // dest= ; 空串. //解碼原則 //原則1: ‘+’變’ ‘; //原則2: ‘%xx’變成對應的16進位ASCII碼值; 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’; } intmain(void) { char *lenstr; char input[MAXINPUT], data[MAXINPUT]; long len; printf(“%s%c%c\n”,”Content-Type:text/html;charset=iso-8859-1”,13,10); printf(“<TITLE>Response</TITLE>\n”); lenstr =getenv(“CONTENT_LENGTH”); printf(“CONTENT_LENGTH =%s\n”,lenstr); if(lenstr == NULL ||sscanf(lenstr,”%ld”,&len)!=1 || len > MAXLEN) { printf(“<P>Error ininvocation - wrong FORM probably.”); } else { FILE *f; fgets(input, len+1, stdin); //add by ycy從輸入資料流中擷取字串. unencode(input+EXTRA, input+len,data); f = fopen(DATAFILE,”a”); if(f == NULL) { printf(“<P>Sorry,cannot store your data.”); } else { fputs(data, f); //add byycy 將資料存放區在對對應的檔案中. } fclose(f); printf(“<P>Thank you!Your contribution has been stored.”); } return 0; }

      請求過程即是:

  (1)      send發送按鈕—>(2)調用post.cgi—>(3)將資料存放區在data\data.txt裡面。

         樣本三、下圖即是GET/POST程式樣本。

  綜合執行個體:在上面兩個程式上的擴充(應用Get方法及QUERY_STRING),

  

  

  如上兩圖所示,在表單(cgi介面的表單只是在html語言的基礎上用C或C++實現的擴充操作而已)的基礎上,提交按鈕對應的另一個CGI介面(6.exe或6.cgi),這樣通過Get方法及QUERY_STRING參量就可以完成輸出操作。

  而POST方法則會將資料送入CGI程式的STDIN輸入資料流。在表單(FORM)中的各個變數都會成為name=value的形式向WEB伺服器發送,多個資料間用&分隔,如:name=value&name2=value2。其中名字(name,name2)是Form中定義的INPUT、SELECT或TEXTAREA等標置(Tag)名字,值是使用者輸入或選擇的標置值。

  如上面說講,在CGI程式輸出時必須先輸出一個CGI標題,標題共有以下三類:

  ·      Location: 標題,指明輸出另一個文檔的URL,例如 fprintf(stdout,”Location: \n\n”);

  ·      Content-Type: 標題,指明發送的資料的MIME類型,例如 fprintf(stdout,”Content-Type:text/html\n\n”);

  ·      Status: 標題,指明HTTP狀態代碼,例如 fprintf(stdout,”Status: 200\n\n”);

  注意每種標題後都必須跟一個換行和一個空行。

  MIME類型以類型/子類型的形式來表示,下面是一些常用的類型/子類型的組合:

  ·      Text/plain 普通文本類型

  ·      Text/html HTML格式的文本類型

  ·      Audio/basic 八位音效檔格式,尾碼為.au

  ·      Video/mpeg MPEG檔案格式

  ·      Video/quicktime QuickTime檔案格式

  ·      Image/gif GIF圖形檔案

  ·      Image/jpeg JPEG圖形檔案

  ·      Image/x-xbitmap X bitmap圖形檔案,尾碼為.xbm

  有了上面的知識我們就可以寫出一些CGI程式,首先需要對輸入資料進行分析,方法為:每當找到字元=,標誌著一個Form變數名字的結束;每當找到字元& ,標誌著一個Form變數值的結束。請注意輸入資料的最後一個變數的值不以&結束。這樣我們可以將輸入資料分解為一組一組的值。

  但隨後會發現CGI的輸入並不規則,例如有時會出現類似下面格式的輸入字元號串:filename=hello&cmd=world+I%27,這是因為瀏覽器對一些上傳的特殊字元進行了編碼,所以在將資料分解開後需要進行解碼,

       解碼規則為:

  1)+: 將+轉換成空格符;

     2) %xx: 用其十六進位ASCII碼值表示的特殊字元(%作為為轉意符)。根據值xx將其轉換成相應的ASCII字元。對Form變數名和變數值都要進行這種轉換。


轉自:http://www.educity.cn/wenda/86802.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.